内核配置与调优入口 —— 到底往哪里写配置
这篇文档是做什么的
做性能调优、改内核行为时,一个反复出现的困惑是:这个参数该往哪儿写?
/proc/sys?/sys?sysctl命令?内核启动参数?它们看着都像"改内核",但作用层次、生效时机、持久化方式完全不同。本篇把内核暴露的所有配置入口梳理成一张地图:每类是什么、改它影响什么、临时改 vs 永久改怎么做、以及一个参数该选哪个入口。
可以回答什么问题
| 问题 | 答案 |
|---|---|
我想改一个内核参数(如 swappiness),该写 /proc/sys 还是 /sys? | §一——全局内核行为走 sysctl//proc/sys |
| 我想把某块盘换成 none 调度器,该写哪里? | §二——设备属性走 /sys |
| 我想隔离几个 CPU 核,运行期改不了怎么办? | §三——isolcpus 必须走内核启动参数,改 GRUB 重启 |
| 改了参数,重启后还在吗? | 见各节"临时 vs 永久"—sysctl 写 /etc/sysctl.d/,/sys 靠 udev/tuned |
| 一个参数该选哪个入口?有没有决策树? | §五——依"改的是什么层次 × 运行期能改吗"决策 |
| 我想一键套用一组调优参数,不用翻十几个文件? | 用 tuned——把 sysctl+sysfs+GRUB 打包成 profile |
相关:
/proc这个虚拟文件系统本身见 procfs(本篇是它"可写的那一面/proc/sys"的延伸 + 其它入口的汇总);具体参数出处散见 free(overcommit/swappiness)、core-dump(core_pattern)、numa、thread-affinity(isolcpus/中断亲和)、tlb(大页)。
零、一句话认知:内核配置分两个维度——"改什么层次" × "活多久"
选入口前,先在脑子里定位两件事:
- 改的是哪一层?
- 全局内核子系统行为(内存/网络/调度) →
sysctl - 某个具体设备/CPU/对象 →
/sys - 开机就要定死、运行期改不了的 → 内核启动参数
- 某个驱动模块 → 模块参数
- 要活多久?
- 只想试一下(重启失效) → 直接写文件
- 要永久 → 写进配置文件(
/etc/sysctl.d/、GRUB、modprobe.d)

核心记忆:能运行期改的全局参数走
sysctl(即/proc/sys);针对某个具体设备/CPU 的属性走/sys;运行期改不了、必须开机定的走内核启动参数(GRUB);驱动相关走模块参数。 临时改就写文件,永久改就写对应的配置文件。
一、/proc/sys 与 sysctl —— 全局内核参数的主入口(90% 的调优在这)
/proc/sys/ 下的文件可写,写入即刻改变内核子系统行为。它和 sysctl 命令是同一套东西——只是路径分隔符不同:
/proc/sys/vm/swappiness ↔ sysctl vm.swappiness (/ 换成 .)
/proc/sys/net/ipv4/... ↔ sysctl net.ipv4...三种改法:临时 / 会话 / 永久
# ① 读
cat /proc/sys/vm/swappiness # 或: sysctl vm.swappiness
# ② 临时改(重启失效)——两种等价写法
echo 10 > /proc/sys/vm/swappiness # 直接写文件
sysctl -w vm.swappiness=10 # sysctl 命令(等价)
# ③ 永久改(重启保留)——写配置文件,别直接 echo
echo 'vm.swappiness = 10' > /etc/sysctl.d/99-tuning.conf
sysctl -p /etc/sysctl.d/99-tuning.conf # 立即加载(不必等重启)
sysctl --system # 重新加载所有 sysctl 配置关键:
echo > /proc/sys/...和sysctl -w都是临时的,重启即失效。要永久必须写进/etc/sysctl.d/*.conf(推荐,模块化)或/etc/sysctl.conf,再sysctl -p。别把 echo 写进 rc.local 之类——用/etc/sysctl.d/才是规范做法。
按子系统分类(常用的几大类)
| 前缀 | 管什么 | 例子(仓库里出现过的) |
|---|---|---|
vm.* | 内存管理 | vm.swappiness(换页倾向)、vm.overcommit_memory(超额分配,见 free)、vm.drop_caches(释放缓存)、vm.nr_hugepages(大页数量,见 tlb) |
net.* | 网络栈 | net.core.somaxconn(连接队列)、net.ipv4.tcp_*(TCP 各种)、net.core.rmem_max(socket 缓冲) |
kernel.* | 内核核心 | kernel.core_pattern(core 文件模板,见 core-dump)、kernel.randomize_va_space(ASLR,见 memory-layout)、kernel.numa_balancing(见 numa)、kernel.sched_*(部分调度参数)、kernel.pid_max |
fs.* | 文件系统 | fs.file-max(全局 fd 上限)、fs.nr_open、fs.inotify.* |
sysctl -a # 列出全部当前参数(几千个)
sysctl -a | grep swappiness # 找某个参数
sysctl net.ipv4 # 看某个子树二、/sys(sysfs)—— 针对具体设备/对象的属性
/sys 也是虚拟文件系统,但组织方式不同:它按内核对象模型(设备、总线、CPU、cgroup…)分层,每个属性一个文件,针对具体的某个对象来配置。sysctl 是"全局开关",/sys 是"逐个对象的旋钮"。
| 路径 | 配置什么 | 出处 |
|---|---|---|
/sys/devices/system/cpu/cpu<N>/... | 单个 CPU:在线状态、调频 governor、缓存拓扑 | 调频/cache-organization |
/sys/devices/system/cpu/cpu<N>/cpufreq/scaling_governor | CPU 频率策略(performance/powersave) | 低延迟调优 |
/sys/kernel/mm/transparent_hugepage/enabled | 透明大页(THP) 开关 | tlb |
/sys/block/<dev>/queue/scheduler | 块设备 IO 调度器(none/mq-deadline/bfq) | iostat |
/sys/block/<dev>/queue/nr_requests、read_ahead_kb | 块设备队列深度、预读 | IO 调优 |
/sys/class/net/<iface>/queues/... | 网卡队列、RPS/XPS 配置 | 网络调优 |
/sys/devices/system/node/node<N>/... | NUMA 节点的内存/CPU 列表 | numa |
/sys/fs/cgroup/... | cgroup v2 的资源限额(CPU/内存/IO) | 容器限额 |
# 例:把某块盘的 IO 调度器改成 none(NVMe 常用),临时
echo none > /sys/block/nvme0n1/queue/scheduler
# 例:关掉透明大页(数据库常见调优)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
# 例:CPU 定频到最高性能(低延迟)
echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
/sys的写入同样临时,重启失效。持久化通常靠udev规则、tuned 配置、systemd unit 或开机脚本——因为它针对具体设备,没有sysctl.conf那样的统一文件。/procvs/sys的分工也见 procfs §六。
三、内核启动参数(cmdline)—— 运行期改不了的,只能开机定
有些参数必须在内核启动时确定,运行期无法更改(比如把某些 CPU 从调度器摘出去、预留大页)。这些走内核命令行(kernel command line),通过 GRUB 配置,改完必须重启。
cat /proc/cmdline # 看当前系统是用哪些启动参数开机的| 启动参数 | 作用 | 出处 |
|---|---|---|
isolcpus=2-5 | 把 CPU 2-5 从调度器默认负载均衡摘出,留给关键线程独占 | thread-affinity |
nohz_full=2-5 | 这些核只有一个任务时关调度时钟中断(tickless),极致低延迟 | thread-affinity |
hugepagesz=1G hugepages=8 | 开机预留 8 个 1G 大页(运行期难分配的连续大页) | tlb |
mitigations=off | 关掉 Spectre/Meltdown 缓解(换性能,见 KPTI) | syscall |
iommu=pt、intel_iommu=on | IOMMU 模式(虚拟化/DPDK/RDMA) | rdma |
transparent_hugepage=never | 启动就关 THP(等价于 sysfs 那个,但开机即定) | — |
永久改法(以常见发行版为例):
# 1) 编辑 /etc/default/grub,在 GRUB_CMDLINE_LINUX 里加参数
# GRUB_CMDLINE_LINUX="... isolcpus=2-5 nohz_full=2-5"
# 2) 重新生成 grub 配置
update-grub # Debian/Ubuntu
grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/CentOS
# 3) 重启生效判据:如果一个参数在
/proc/sys或/sys里找不到对应可写文件,或改了报错/不生效,它多半是只能开机定的启动参数。isolcpus、大页预留就是典型——运行期内核已经把资源分配格局定死了,改不动。
四、其它专项入口
- 模块参数(module parameters):某个内核模块(驱动)的参数。
- 临时(加载时):
modprobe <mod> param=value;运行期部分可改:/sys/module/<mod>/parameters/<param>。 - 永久:写
/etc/modprobe.d/*.conf(如options nvme poll_queues=4)。
- 临时(加载时):
ethtool:网卡专项配置(多队列/RSS、offload、ring buffer 大小、中断合并 coalescing)——很多网络调优不在 sysctl 而在ethtool。- tuned /
tuned-adm:发行版提供的调优配置集(profile),一键套用一组 sysctl+sysfs+cmdline 设置(如throughput-performance、latency-performance)。生产环境常用它统一管理,而非手改一堆文件。详见 tuned。 ulimit//etc/security/limits.conf:进程资源限制(fd 数、栈大小、core 大小)——属于每进程/每用户层面,不是全局内核参数(对应 task-struct 的rlimit、procfs 的/proc/<pid>/limits)。- cgroup:给一组进程限额(CPU/内存/IO),cgroup v2 通过
/sys/fs/cgroup/下的文件配置——容器(Docker/K8s)的资源限制底座(见 task-struct §2.6)。
五、决策:一个参数该往哪写

| 想调的东西 | 入口 | 临时 | 永久 |
|---|---|---|---|
| 换页/超额/TCP/ASLR/core_pattern 等全局行为 | sysctl | sysctl -w 或 echo>/proc/sys | /etc/sysctl.d/*.conf |
| 某盘 IO 调度器、THP、CPU governor | /sys | echo>/sys/... | udev 规则 / tuned |
| 隔离 CPU、预留大页、关 mitigations | 启动参数 | (不可) | GRUB → 重启 |
| 驱动行为 | 模块参数 | /sys/module/.../parameters | /etc/modprobe.d/ |
| 网卡队列/offload/中断合并 | ethtool | ethtool -X/-G/-C | 开机脚本 / NetworkManager |
| 一组参数一键套用 | tuned | tuned-adm profile X | tuned 持久 |
| 每进程 fd/栈/core 上限 | ulimit | ulimit -n | /etc/security/limits.conf |
六、调优效果验证(改完参数后用什么工具看效果)
| 调了什么 | 用什么验证 | 看什么指标 |
|---|---|---|
| vm.swappiness / 内存相关 | free -h + vmstat 1 | available、si/so 是否改善 |
| net.core.* / TCP 参数 | ss -ti + sar -n DEV/ETCP | rtt、retrans、带宽是否改善 |
| CPU governor (performance) | mpstat -P ALL 1 | %usr/%sys 是否稳定、有无限频 |
| THP 关闭 | cat /proc/meminfo | grep AnonHuge | AnonHugePages 应为 0 |
| IO 调度器 (none/mq-deadline) | iostat -x 1 | await、aqu-sz 是否下降 |
| isolcpus 隔离 | cat /proc/cmdline + taskset | 确认调度器不会把任务放到隔离核 |
| 大页预留 | cat /proc/meminfo | grep HugePages | HugePages_Free/HugePages_Total |
| 网卡队列/中断合并 | ethtool -l/-g/-c + mpstat -P ALL 1 | %soft 分布是否均匀、中断均衡 |
七、调优通则(别瞎改)
- 一次只改一个:同时改多个参数,出问题分不清是谁。
- 临时验证 → 确认有效 → 才持久化:先 echo/
sysctl -w跑一段观察,确认没副作用再写进配置文件。改错的全局参数(overcommit、core_pattern、TCP 参数)可能拖垮整机。 - 记下默认值:改之前 cat 存一份原值,好回滚。
- 生产优先用 tuned/配置管理:手改散落文件难维护,用 tuned profile 或 Ansible 之类统一管。
八、和本仓库其他文档的关系
/proc本体:procfs——本篇是它"可写的/proc/sys"那一面的展开 + 其它入口汇总;二者配合看。- 各参数的语境:free(vm.overcommit/swappiness)、core-dump(kernel.core_pattern)、memory-layout(randomize_va_space/ASLR)、numa(numa_balancing)、tlb(大页)、thread-affinity(isolcpus/nohz_full/中断亲和)、interrupts(smp_affinity)、iostat(IO 调度器)。
- 每进程/每组限额:task-struct(rlimit、cgroup)。
九、一句话总结
内核配置按"改哪层 × 活多久"两个维度选入口:全局内核行为(内存/网络/内核/文件系统)走 sysctl(即
/proc/sys,sysctl -w或 echo 临时改、写/etc/sysctl.d/*.conf永久);针对具体设备/CPU/盘/cgroup 的属性走 /sys(sysfs,持久化靠 udev/tuned);运行期改不了、必须开机定的(isolcpus、预留大页、关 mitigations)走内核启动参数**(改 GRUB→重启);驱动走模块参数,网卡走 ethtool,一组参数一键套用走 tuned,每进程资源上限走 ulimit。判据:能运行期改的全局参数=sysctl,找不到可写文件/改了不生效的多半是启动参数。所有调优都要先测量、一次改一个、临时验证后再持久化。**