内核内部 —— 调度器、网络栈、文件系统

服务器运维的”硬核”调优都落在内核子系统上——CPU 调度、网络协议栈、文件系统。本文按三大子系统展开。

一张全景

graph TB
  K[Linux Kernel]
  K --> SCH[进程调度
CFS / EEVDF / sched_ext] K --> NET[网络栈
TCP/IP / XDP / eBPF] K --> FS[文件系统
ext4 / XFS / Btrfs / ZFS] K --> MM[内存管理
NUMA / Page / Huge Page] K --> IO[IO 子系统
blk-mq / io_uring] K --> SEC[安全
SELinux / Seccomp / capabilities]

进程调度

CFS(Completely Fair Scheduler)

Linux 默认调度器(2.6.23+,2007):

1
2
3
4
5
6
7
8
设计:     基于"虚拟运行时间"的红黑树
目标: 公平分配 CPU 时间
关键数据结构: 红黑树 / 任务的 vruntime

调度决策:
- 选 vruntime 最小的任务运行
- 周期性 tick 更新 vruntime
- 抢占点检查

CFS 的几个调优参数:

1
2
3
4
5
6
7
8
# /proc/sys/kernel/
sched_min_granularity_ns # 最小调度粒度,默认 750000 ns
sched_wakeup_granularity_ns # 唤醒抢占粒度,默认 1000000 ns
sched_migration_cost_ns # 迁移成本,默认 500000 ns
sched_latency_ns # 调度周期,默认 6000000 ns

# 调优
sysctl -w kernel.sched_migration_cost_ns=5000000 # 不轻易迁核

EEVDF(2023+)

Linux 6.6 默认替代 CFS:

1
2
3
4
5
EEVDF(Earliest Eligible Virtual Deadline First):
- 借鉴 1995 年学术论文
- 比 CFS 在低延迟场景表现更好
- 适配现代多核多 NUMA 工作负载
- 6.6 LTS 默认

CFS vs EEVDF 是 Linux 调度器 16 年来最大变化。

sched_ext(可插拔调度器)

1
2
3
4
5
6
7
8
9
sched_ext(6.12+):
- 用 BPF 实现自定义调度器
- 不需要重新编译内核
- 实验性,Meta 主推

应用:
- 数据库专用调度器
- 游戏低延迟调度器
- AI 训练调度器

实时调度

1
2
3
4
5
6
SCHED_NORMAL(默认):     CFS
SCHED_FIFO: 先进先出实时
SCHED_RR: 轮转实时
SCHED_DEADLINE: 截止时间调度
SCHED_IDLE: 低优先级
SCHED_BATCH: 批处理任务
1
2
3
4
5
6
7
8
# 设置实时优先级
chrt -f 99 ./mysql # FIFO 99
chrt -p <pid> # 查看
chrt -p -f 50 <pid> # 改

# nice 调度
nice -n 10 ./batch_job
renice -n 5 -p <pid>

调度域和 NUMA

第二章已经讲过 NUMA——内核通过 scheduling domain 知道拓扑:

1
2
3
4
5
6
# 看调度域
cat /proc/sys/kernel/sched_domain/cpu0/domain*/name

# NUMA 信息
numactl -H
numactl --cpunodebind=0 --membind=0 ./app

CPU 亲和力工具:

1
2
taskset -c 0-7 ./app             # 绑核 0-7
taskset -p -c 0-7 <pid> # 改进程绑定

网络协议栈

graph TB
  APP[应用]
  APP --> SOCKET[socket layer]
  SOCKET --> TCP[TCP / UDP / SCTP]
  TCP --> IP[IPv4 / IPv6]
  IP --> NETF[netfilter / nftables]
  NETF --> QDISC[Qdisc / Traffic Control]
  QDISC --> NIC[NIC driver]
  NIC --> HW[硬件网卡]
  
  XDP[XDP] -.- NIC

TCP 拥塞控制

1
2
3
4
5
6
7
8
Linux 支持的拥塞控制算法:
reno: 最早,已过时
cubic: Linux 默认(2007 起)
bbr: Google 出品(2016),延迟感知
bbr2: 改进版
bbr3: 最新
dctcp: 数据中心专用
westwood: 改进 reno
1
2
3
4
5
6
7
8
9
10
# 看可用算法
sysctl net.ipv4.tcp_available_congestion_control

# 当前用
sysctl net.ipv4.tcp_congestion_control

# 改成 BBR
modprobe tcp_bbr
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq

BBR 在长肥管道(LFN)上表现更好——视频流 / 跨地域传输的标配。

TCP 调优参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 缓冲区大小(10G+ 网卡建议调大)
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
sysctl -w net.ipv4.tcp_rmem="4096 87380 134217728"
sysctl -w net.ipv4.tcp_wmem="4096 65536 134217728"

# 连接队列
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535

# TIME_WAIT 复用
sysctl -w net.ipv4.tcp_tw_reuse=1

# Fast Open
sysctl -w net.ipv4.tcp_fastopen=3

# 持久化
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.d/99-tuning.conf
sysctl --system

XDP:高速包处理

XDP(eXpress Data Path)让 BPF 程序在网卡驱动层就处理包——包没进网络栈就被处理

graph LR
  NIC[网卡] --> XDP[XDP BPF]
  XDP --> D1{决策}
  D1 -- DROP --> X[丢弃]
  D1 -- TX --> NIC
  D1 -- REDIRECT --> NIC2[其他网卡]
  D1 -- PASS --> NS[正常网络栈]

性能:

1
2
3
XDP_DROP(DDoS 防护):     20+ Mpps / 核
XDP_TX(负载均衡): 10-15 Mpps / 核
传统 iptables: 几百 Kpps / 核

应用:

1
2
3
4
- DDoS 防护(Cloudflare、Facebook)
- 负载均衡(Katran)
- 抓包(xdpdump)
- 加速容器网络(Cilium)

netfilter / nftables

1
2
3
4
5
6
7
8
9
10
11
12
iptables(传统):
- 规则线性匹配,N 条规则 O(N) 性能
- 内核已不主推

nftables(现代):
- 哈希表匹配,性能 O(1)
- 命令更简洁
- RHEL 8+ / Ubuntu 20.04+ 默认
- iptables 命令可作为 nftables 兼容层

iptables → nftables 迁移:
iptables-translate "iptables -A INPUT ..."

IPVS

1
2
3
4
5
IPVS(IP Virtual Server):
- 内核 L4 负载均衡
- 比 iptables 快很多
- K8s kube-proxy 支持 IPVS 模式
- LVS(Linux Virtual Server)项目核心

文件系统

graph TB
  FS[Linux 文件系统]
  FS --> LOCAL[本地]
  FS --> NETWORK[网络]
  FS --> SPECIAL[特殊]
  
  LOCAL --> EXT[ext2/3/4]
  LOCAL --> XFS[XFS]
  LOCAL --> BTRFS[Btrfs]
  LOCAL --> ZFS[ZFS]
  LOCAL --> F2FS[F2FS]
  
  NETWORK --> NFS[NFS]
  NETWORK --> CIFS[CIFS/SMB]
  NETWORK --> CEPHFS[CephFS]
  NETWORK --> GLUSTER[GlusterFS]
  
  SPECIAL --> PROC[/proc]
  SPECIAL --> SYS[/sys]
  SPECIAL --> TMPFS[tmpfs]
  SPECIAL --> OVERLAY[OverlayFS
容器用]

ext4

1
2
3
4
5
6
7
8
ext4:     
- Linux 默认(多数发行版)
- 经久耐用
- 单文件最大 16 TB
- 单卷最大 1 EB
- 不支持原生压缩 / 快照

仍是企业 Linux 服务器最常用的根文件系统。

XFS

1
2
3
4
5
6
7
8
9
XFS:     
- SGI 1993 年 IRIX 移植到 Linux
- 大文件性能好
- 默认延迟分配
- 单卷最大 8 EB
- RHEL 7+ 默认根文件系统
- 不支持 shrink(缩容)

适用: 大文件场景,数据库,存储节点

Btrfs

1
2
3
4
5
6
7
8
9
10
11
12
13
Btrfs:     
- "B-tree FS"
- 写时复制(COW)
- 原生快照、子卷、压缩、RAID
- 单卷最大 16 EB
- SUSE 默认(openSUSE / SLES)

历史问题:
- 早期 RAID 5/6 不稳
- 大量碎片场景性能差
- Red Hat 已不再支持

适用: SUSE 系,桌面,开发机

ZFS

1
2
3
4
5
6
7
8
9
10
ZFS:     
- Sun 1995 起开发,开源
- 写时复制 + 校验和 + 压缩 + 去重
- 软件 RAID(RAIDZ)
- 单池可达 256 ZiB
- License 问题不能合入 Linux 内核
- Ubuntu 通过 DKMS 模块支持
- 数据完整性最强

适用: 存储节点、备份、文件服务器

NFS

1
2
3
4
5
6
7
8
9
10
11
NFS(Network File System):     
- Sun 1984 起,跨平台
- NFSv3:无状态,老但稳
- NFSv4:有状态,加密
- NFSv4.1 / pNFS: 并行 NFS
- NFSv4.2: 新特性

调优:
- mount -o rsize=1048576,wsize=1048576,vers=4.2
- 异步 / 同步选择
- 端口 2049

CephFS / GlusterFS

1
2
3
4
5
6
7
8
CephFS:     
- Ceph 存储集群提供 POSIX 文件系统
- 元数据服务器(MDS)
- 客户端 ceph-fuse 或内核 cephfs

GlusterFS:
- Red Hat 主推,已下马
- 不需要专门元数据服务器

第四章已介绍。

OverlayFS

容器镜像分层的核心:

1
2
3
4
5
6
OverlayFS:     
- lowerdir:镜像层(只读)
- upperdir:容器写入层
- merged:合并视图

Docker / containerd 默认 storage driver

tmpfs

1
2
3
4
5
tmpfs:     
- 内存中的文件系统
- 关机消失
- /tmp / /run / /dev/shm 默认
- 大小可指定(默认半内存)

内存管理

graph TB
  MM[Memory Management]
  MM --> PG[Page Allocator
buddy system] MM --> SLAB[SLAB / SLUB
对象缓存] MM --> VMA[VMA / mmap] MM --> SWAP[Swap] MM --> OOM[OOM Killer] MM --> NUMA[NUMA Allocator] MM --> THP[Transparent Huge Pages]

Huge Pages

减少 TLB miss,对大内存应用很重要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 看大页配置
cat /proc/meminfo | grep -i huge

# 静态大页 2 MB
echo 8192 > /proc/sys/vm/nr_hugepages
mkdir /mnt/hugepages
mount -t hugetlbfs none /mnt/hugepages

# 1 GB 大页(启动参数)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=64"

# Transparent Huge Pages(动态)
cat /sys/kernel/mm/transparent_hugepage/enabled
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled

# THP 三选项:
# always: 自动用大页(数据库可能慢)
# madvise: 应用主动 madvise 才用(推荐)
# never: 禁用

数据库(Oracle / PostgreSQL / MongoDB)建议关 THP 改静态大页。

Swap

1
2
3
4
5
6
7
8
9
10
11
12
13
# 看 swap
swapon -s
free -h

# swappiness(0-100,越高越爱用 swap)
cat /proc/sys/vm/swappiness # 默认 60
sysctl -w vm.swappiness=10 # 服务器一般调小

# swap 文件
fallocate -l 16G /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile none swap sw 0 0" >> /etc/fstab

数据库 / 大内存机器通常 swap = 0 或很小——别让 swap 拖累性能

OOM Killer

1
2
3
4
5
6
7
8
内存耗尽时杀进程:
- OOM Score 计算(/proc/<pid>/oom_score)
- 优先杀大的、可恢复的
- 重要进程 echo -1000 > /proc/<pid>/oom_score_adj 不被杀

调整:
- vm.overcommit_memory = 0/1/2
- vm.overcommit_ratio = 50(百分比)

IO 子系统

graph TB
  APP[应用 read/write]
  APP --> VFS[VFS 抽象层]
  VFS --> FS[具体文件系统]
  FS --> BIO[block IO 层]
  BIO --> SCHED[IO 调度器]
  SCHED --> DRV[块设备驱动]
  DRV --> HW[硬件 SSD/HDD]

IO 调度器(blk-mq)

1
2
3
4
5
6
7
8
9
10
现代 Linux blk-mq 多队列:
none: 无调度,对 NVMe 默认
mq-deadline: deadline 改进
bfq: 公平调度
kyber: 低延迟

NVMe 用 none:
cat /sys/block/nvme0n1/queue/scheduler

原因:硬件已经多队列,软件调度反而拖累
1
2
3
# 改 IO 调度器
echo none > /sys/block/nvme0n1/queue/scheduler
echo mq-deadline > /sys/block/sda/queue/scheduler

io_uring

7.1 已介绍——异步 IO 革命。配套 API:

1
2
3
4
5
io_uring_queue_init();
io_uring_get_sqe();
io_uring_prep_read();
io_uring_submit();
io_uring_wait_cqe();

应用:

1
2
3
PostgreSQL 17+:     io_uring 后端
ScyllaDB: 原生 io_uring
Tokio(Rust 异步): io_uring 支持

安全子系统

SELinux / AppArmor

1
2
3
4
5
6
7
8
9
SELinux(Red Hat):     
- 标签 / 类型强制
- 默认严格
- RHEL / Fedora 默认 enforcing

AppArmor(Ubuntu):
- 路径基础
- 比 SELinux 简单
- Ubuntu / Debian 默认
1
2
3
4
5
6
7
8
# SELinux
getenforce
setenforce 0 # 临时关
semanage / restorecon

# AppArmor
aa-status
aa-enforce / aa-complain

Seccomp

1
2
3
4
5
6
7
8
9
Seccomp:     系统调用白名单
- 进程限制只能调几个 syscall
- 容器逃逸防护
- Docker 默认 seccomp profile

应用:
- 容器(Docker / K8s)
- 沙箱(Chromium、Firefox)
- 不可信代码执行

capabilities

1
2
3
4
5
6
7
8
传统 root:     全权或全无权
capabilities: 细粒度
CAP_NET_ADMIN: 管网络
CAP_SYS_ADMIN: 管系统(万能)
CAP_NET_BIND_SERVICE: 绑端口 < 1024
...

容器默认 drop ALL,再 add 必需的几个。

内核参数总览

1
2
3
4
5
6
7
8
9
10
11
12
13
# 看所有 sysctl
sysctl -a

# 常用调优文件
/etc/sysctl.conf
/etc/sysctl.d/*.conf

# 临时改
sysctl -w net.core.somaxconn=65535

# 持久化
echo "net.core.somaxconn=65535" >> /etc/sysctl.d/99-tuning.conf
sysctl --system

服务器一般调优起点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# /etc/sysctl.d/99-server.conf

# 网络
net.core.somaxconn = 65535
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30

# 内存
vm.swappiness = 10
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5

# 文件
fs.file-max = 2097152
fs.nr_open = 1048576

# 进程
kernel.pid_max = 4194304

内核 BPF 工具

1
2
3
4
5
6
7
8
9
# bpftrace 一行命令
bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("%s\n", str(args->filename)); }'

# 常见 BCC 工具
opensnoop # 看打开文件
execsnoop # 看进程执行
biolatency # 看 IO 延迟分布
tcpconnect # 看 TCP 连接
runqlat # 看运行队列延迟

BPF 工具是排障神器——比 strace 快几十倍

一些查询命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# CPU
mpstat -P ALL 1
top / htop / btop
pidstat 1
perf top
perf stat / perf record

# 内存
free -h
vmstat 1
cat /proc/meminfo
slabtop

# 网络
ss -s # socket 总览
ss -tnp # TCP 连接
iftop / nethogs # 流量
ethtool -S eth0 # 网卡统计
tcpdump -i eth0 -w cap.pcap

# 磁盘
iostat -x 1
iotop
dstat # 综合
fio # 性能测试

# 内核日志
dmesg
journalctl -k # kernel logs
journalctl --since "1 hour ago"

内核调优的方法论

graph TD
  M[Measure 测量]
  M --> A[Analyze 分析瓶颈]
  A --> H[Hypothesize 假设]
  H --> C[Change 改一项]
  C --> V[Verify 验证]
  V --> M
1
2
3
4
5
6
Brendan Gregg 的"USE 方法":     
Utilization: 利用率
Saturation: 饱和度(队列、等待)
Errors: 错误数

每次只改一项 → 测量对比 → 不要改"一堆"。

内核版本与新特性查询

1
2
3
4
5
6
7
8
9
10
11
uname -r                              # 内核版本

# 新特性查询(编译开关)
zcat /proc/config.gz | grep <FEATURE>
# 或
cat /boot/config-$(uname -r) | grep <FEATURE>

# 模块管理
lsmod | grep <module>
modprobe <module>
modinfo <module>

一些数字直觉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
syscall 开销:     
read/write: 几十 ns
socket: 几百 ns
fork: 几十 μs
exec: 几百 μs

内存访问:
L1 cache: 1 ns
L2 cache: 5 ns
L3 cache: 30 ns
本地 DRAM: 100 ns
远端 NUMA: 200 ns
HBM: ~50 ns

文件系统:
ext4 顺序读: >5 GB/s(NVMe)
XFS 大文件: >10 GB/s
本地 NVMe 4K 随机读: 500K-1M IOPS

网络:
本地 ping: 几十 μs
同机房 ping: < 1 ms
跨城 ping: ~10-50 ms
跨国 ping: ~100-200 ms

小结

  • Linux 内核三大子系统:调度(CFS/EEVDF)、网络(TCP/IP/XDP)、文件系统(ext4/XFS/Btrfs/ZFS)
  • io_uring + eBPF 是近年内核最重要新特性
  • TCP BBR 是长肥管道的拥塞控制选择
  • nftables 已替代 iptables
  • THP 在数据库要谨慎用
  • BPF / bpftrace 是排障神器
  • 调优要”测量-假设-改一项-验证”循环

下一篇讲 AI 时代 OS 适配——vGPU、NPU 调度、大模型训练 OS 优化。