操作系统层裁剪:内核模块精简、禁用不必要的系统服务、调整内核参数
系统裁剪这件事,很多人一上来就盯着应用层优化。但我个人的习惯是——先看操作系统本身。你想想看,一个系统里跑着几十个用不上的服务、加载了一堆你根本不会用到的内核模块,它怎么可能快得起来?
说白了,操作系统层裁剪是性价比最高的优化手段。不需要改代码,不需要换硬件,只要把那些「吃闲饭」的组件拿掉,性能就能明显提升。我在项目中遇到过一台服务器,裁剪前 idle 进程只占 30%,裁剪后直接飙到 75%。嗯,这就是我们今天要聊的内容。
内核模块精简:把不需要的「零件」拆掉
Linux 内核默认编译了很多模块。这些模块就像工具箱里你永远不会用到的扳手——它们占地方,还拖慢启动速度。
第一步:看看你加载了哪些模块
# 查看当前已加载的模块
lsmod
# 查看所有可用模块(包括未加载的)
find /lib/modules/$(uname -r) -name "*.ko" | wc -l
我见过一个默认安装的 CentOS 系统,内核模块数量超过 3000 个。而实际用到的,往往不到 200 个。剩下的那些,就是你可以裁剪的对象。
第二步:确定哪些模块可以移除
我个人习惯按这个思路来筛选:
- 硬件无关的模块:比如你用的是 Intel 网卡,那所有 Realtek、Broadcom 的网卡驱动都可以删掉
- 文件系统模块:只用 ext4,那 btrfs、xfs、zfs 的模块都可以去掉
- 网络协议模块:不需要 IPv6 就干掉 ipv6.ko,不需要 netfilter 就清理 iptables 相关模块
- 安全模块:SELinux、AppArmor 如果不用,直接禁用
第三步:重新编译内核或使用 modprobe 黑名单
如果你不想重新编译内核(说实话,大部分场景没必要),可以用黑名单机制:
# 创建黑名单配置文件
echo "blacklist ipv6" >> /etc/modprobe.d/disable-ipv6.conf
echo "blacklist btusb" >> /etc/modprobe.d/disable-bt.conf
# 更新 initramfs
dracut --force
重新编译内核的话,我建议用 make localmodconfig。这个命令会根据当前系统加载的模块自动生成一个精简配置。我在一个嵌入式项目里用过,内核体积从 120MB 降到了 18MB,启动时间从 45 秒缩短到 8 秒。
禁用不必要的系统服务:别让它们偷走你的 CPU
系统服务是另一个「隐形杀手」。很多服务默认开机自启,但你根本用不上。
先看看当前有哪些服务在跑:
# systemd 系统
systemctl list-units --type=service --state=running
# 查看开机自启的服务
systemctl list-unit-files --type=service --state=enabled
我整理了一份常见的「可禁用服务清单」,你可以对照着检查:
| 服务名称 | 用途 | 建议 |
|---|---|---|
| bluetooth.service | 蓝牙支持 | 服务器环境直接禁用 |
| cups.service | 打印服务 | 99% 的服务器用不到 |
| avahi-daemon.service | 零配置网络发现 | 内网环境可禁用 |
| postfix.service | 邮件传输 | 不需要发邮件就关掉 |
| firewalld.service | 防火墙 | 如果用了 iptables 或 nftables 可禁用 |
| NetworkManager.service | 网络管理 | 服务器建议用 systemd-networkd 替代 |
systemctl mask 而不是 systemctl disable。mask 会彻底阻止服务被启动(包括被其他服务依赖触发),而 disable 只是不让它开机自启。
禁用命令示例:
systemctl stop bluetooth.service
systemctl mask bluetooth.service
我曾经在一台 2C4G 的云服务器上,禁用了 12 个不必要的服务。重启后,内存占用从 1.2GB 降到了 480MB。你想想看,这省下来的 700 多 MB 内存,留给业务进程多好。
调整内核参数:用最小的改动换最大的收益
内核参数调整是系统裁剪的「点睛之笔」。不需要删东西,改几个数值就能看到效果。
网络栈优化
如果你的系统主要做网络 I/O,这几个参数值得关注:
# 在 /etc/sysctl.conf 中添加以下内容
# 增大 TCP 连接队列长度
net.core.somaxconn = 65535
# 减少 TIME_WAIT 状态的连接数
net.ipv4.tcp_fin_timeout = 15
# 开启 TCP 快速回收(注意:仅适用于非 NAT 环境)
net.ipv4.tcp_tw_reuse = 1
# 增大 socket 缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
tcp_tw_recycle 这个参数在 Linux 4.12 之后已经被移除了。如果你还在用旧内核,千万别开这个——它在 NAT 环境下会导致严重的连接问题。我踩过这个坑,线上故障排查了整整两天。
内存管理优化
对于内存敏感的场景,我建议调整这些:
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| vm.swappiness | 60 | 10 | 减少 swap 使用倾向,优先用物理内存 |
| vm.dirty_ratio | 20 | 10 | 降低脏页比例,减少 I/O 抖动 |
| vm.vfs_cache_pressure | 100 | 50 | 减缓 dentry/inode 缓存回收 |
| kernel.numa_balancing | 1 | 0 | 关闭 NUMA 自动平衡(单 socket 场景) |
文件系统优化
如果你用的是 SSD,记得调整 I/O 调度器:
# 查看当前调度器
cat /sys/block/sda/queue/scheduler
# 设置为 none(NVMe SSD 推荐)或 mq-deadline
echo "none" > /sys/block/sda/queue/scheduler
# 永久生效(通过 udev 规则)
echo 'ACTION=="add|change", KERNEL=="sd*", ATTR{queue/scheduler}="none"' > /etc/udev/rules.d/60-iosched.rules
为什么这么做?传统的 CFQ 调度器会对 I/O 请求做复杂的排序和合并,这在 HDD 时代有用,但在 SSD 上反而增加了延迟。直接设为 none,让硬件自己处理,性能提升很明显。
本章核心知识体系
下面这张图总结了操作系统层裁剪的三个维度和它们之间的关系:
总结一下:操作系统层裁剪不是一锤子买卖。我建议你每做一次改动,就用 perf stat 或 time 命令记录一下前后的性能数据。这样你才能知道哪些改动真正有效,哪些只是心理安慰。
另外,别忘了做回归测试。我曾经因为禁用了 systemd-journald,导致日志丢失,排查线上问题花了三倍时间。嗯,这个教训挺深刻的。