认识 Linux 内核:一份给初学者的笔记

整理自 Open Source Summit North America 2023 演讲
Getting to Know the Linux Kernel: A Beginner’s Guide
讲者:Kelsey Steele、Nischala Yelchuri(Microsoft Linux 内核团队)
原视频:YouTube · 幻灯片:PDF · 日程:OSSNA 2023

这不是一篇「从零手写内核」的教程,而是一张地图:内核是什么、源码怎么摆、配置和编译怎么起步、测试怎么做、上游社区怎么运转。两位讲者反复强调一件事——没有人能把内核全部学会,这既让人兴奋,也容易让人却步。入门的正确姿势不是一次吃完,而是先建立坐标系,再按子系统往下钻。


讲者是谁

  • Kelsey Steele:Microsoft 软件工程师,维护 WSL2 内核。2020 年毕业于科罗拉多州立大学,经 Linux Foundation 的 Kernel Mentorship Program 入门,早期做 PCI 子系统。
  • Nischala Yelchuri(口播里常叫 Nisha):同在 Microsoft Linux Systems Group。此前在 Azure Sphere OS 内核团队,重点做内存优化,并用 cgroups 限制资源占用。

她们的目标很明确:帮你搞清楚「从哪里拿源码、怎么改、怎么编、怎么测、怎么把改动送回上游」。细节留给文档和社区,课上只给能自己继续查的概念。


内核到底是什么

每个操作系统都有内核。Linux 内核是 Linux 系统的核心层,负责:

  • 硬件与软件之间的交互
  • 多任务与进程调度
  • 内存管理
  • 输入输出
  • 把用户程序和真实设备隔开、再连起来

Linus Torvalds 在 1991 年写出第一版。三十多年后,全球有数千名贡献者,很多公司都有自己的内核团队。大家共同协作的主干叫做 Upstream(上游内核)。发行版内核、云厂商内核、WSL2 内核,几乎都是「上游 + 本地定制」。

健康的产品策略通常是:

  1. 尽量把通用改动送回上游;
  2. 产品内核尽量贴近上游,减少自己要长期背的补丁。

Kelsey 用 WSL2 举例:他们有独立的 GitHub 仓库和定制,但更新仍尽量从上游拉取。


先记住六块积木

内核很大,但高层结构并不神秘。可以先按子系统建立心智模型。

1. 进程管理

管进程的一生:创建、调度到某个 CPU、退出。调度算法也在这里。用户态看到的「很多程序同时跑」,底层是内核在切时间片、排优先级。

2. 内存管理

分配、回收、映射物理内存和虚拟内存。源码大致在 mm/。改分配器这类改动很「吓人」,因为它会牵动内核里几乎所有人。

3. 虚拟文件系统(VFS)

VFS 是一层抽象。用户程序调用 read / write 等系统调用时,先进入统一接口,再分发到 ext4、XFS、NFS 等具体文件系统。源码在 fs/

4. 网络栈

从应用层 socket,经过 TCP/IP,一直到网卡驱动。源码在 net/

5. 设备驱动

键盘、鼠标、显示器、网卡……硬件插上之后,谁来认、谁来管,主要是驱动子系统。

6. 架构相关代码(arch)

前面多数逻辑是「处理器无关」的。真正和 x86、ARM、RISC-V 绑定的部分在 arch/。换 CPU 架构时,差异主要落在这里。

源码目录和子系统的对应图,课上引用了:

记住这张地图就够了。真要改某一块,再进对应目录。


源码从哪拿

官方入口只有一个:https://www.kernel.org/

页面上能看到几类版本:

  • Mainline:主线,新功能从这里进
  • Stable:主线发布后的稳定维护
  • Longterm(LTS):被选中长期维护的稳定内核

发行版提供的内核包,多半已经带了发行版自己的补丁。想看「原版」,去 kernel.org;想跟某个发行版行为一致,再去发行版的内核仓库。

两种都合理,取决于你的目标是学上游,还是修自己机器上正在跑的那份内核。


定制内核:先改配置,再改代码

这是整场演讲里最解放人的一句:不必先精通 C 或 Rust,也能开始玩内核。

更低门槛的入口是配置系统,也就是 .config

配置能做什么

  • 打开或关掉功能
  • 缩小体积、换性能取向
  • 增加某种硬件支持
  • 打开调试选项
  • 调整安全相关开关

常用命令

make menuconfig   # 文本菜单,课上演示的就是这个
make xconfig      # 图形界面
make oldconfig    # 拿旧 .config 适配新版本内核
make defconfig    # 生成当前架构的推荐默认配置

直接手改 .config 可以,但不推荐——依赖关系很容易改乱。

什么时候才改代码

配置不够用时,才进源码。常见场景:

  • 加功能、写自定义驱动
  • 改安全策略或访问控制
  • 修 bug、修漏洞
  • 针对特定硬件做优化
  • Backport:产品必须停在较老的稳定内核上,但需要把新版本里的关键修复「移植回来」

发行版团队大量日常工作就是 backport,而不是永远跟最新主线。稳定和新鲜,常常不可兼得。


编译、安装、以及那条不能忘的警告

具体步骤因发行版而异。课上的通用流程摘自 KernelNewbies: KernelBuild

通用步骤

  1. 安装编译依赖(gccmakebisonflexlibncurses 等,以发行版文档为准)。
  2. 在源码树里执行:
make -j$(nproc)

第一次会很慢。增量编译会快很多;make clean 之后又会变慢。讲者还放了 xkcd 303:编译开始后,唯一能做的事就是去倒咖啡。

  1. 安装模块和内核:
sudo make modules_install
sudo make install

Ubuntu 等发行版有时要求先打成 deb 再装,不要死记这一套命令,以发行版文档为准。

  1. 更新 GRUB(或你正在用的引导器),重启,选新内核。

必须记住的安全网

  • 至少留一个能启动的旧内核。
  • 新内核坏了,机器可能直接起不来。
  • 初学者请先用虚拟机。玩坏了,删掉虚机重来,不要拿日常工作电脑练手。

内核开发的第一课不是写代码,是给自己留退路。


怎么知道自己没改坏

测试方式和改动性质有关,没有万能套餐。

小改动

比如把某个变量从 u32 改成 u64

  • printk
  • dmesg 看内核日志

够快,也够直观。

大改动

新功能、换内存分配器、动到全局路径,需要系统化测试。

工具 位置 大约耗时 适合什么
LTP 内核树外 全量 3–4 小时 稳定性、可靠性、回归
kselftest 内核树内,程序跑在用户态 约 20–30 分钟 用户态与内核交界,例如系统调用

经验规则:如果你加了一条新 syscall,最好同时加一条 kselftest。

开发期检查

  • checkpatch:风格和常见错误。往上游发补丁前几乎人人跑。
  • KASAN / KMEMLEAK 等动态工具:查越界、use-after-free、泄漏。
  • ftracedump_stack():看调用路径。
  • objdumpaddr2lineGDB:把地址翻译回源码位置。

调试资料:


上游是怎么流动的

内核不是一个仓库里所有人一起推 main。它是一组树:

维护者 干什么
Mainline Linus Torvalds 主线和新功能,以及 RC
Stable Greg Kroah-Hartman 稳定分支,收 bugfix
linux-next Stephen Rothwell 把各子系统即将合入的改动提前集成、暴露冲突
Subsystem trees 各子系统维护者 网络、内存、驱动等各自的开发树

一条补丁的典型人生:

开发者 → 子系统维护者的树 → linux-next → Linus 的主线 → Stable / LTS → 发行版和产品内核

发行节奏

大约每 9–10 周 一个主线版本:

  • Merge window:约 2 周,合新功能
  • 修复与稳定:约 7–8 周,出一串 -rc
  • 正式发布后,该版本进入 Stable

LTS(Long-term Support) 是从 Stable 里选出来的长期分支,至少维护约两年,只收修复、不加功能。发行版和产品环境最常跟的就是它。

所以「最新内核」和「该上生产的内核」通常不是同一个东西。


社区不在 Issue 区,在邮件列表

内核开发者的主战场是邮件列表,服务站点是 vger.kernel.org

实用建议:

  • 按兴趣订子系统列表,例如 BPF、KVM、文档、newbie。
  • 不要随手订阅 linux-kernel(LKML)。 流量极大,每天成百上千封,邮箱会被灌爆。
  • 检索历史讨论用 lore.kernel.org,比把所有列表都订下来更重要。

课上列出的部分列表规模(2023 年快照,只说明量级,不必当现行数据):

  • linux-kernel:约 2800 订阅
  • linux-newbie:约 1200
  • KVM、Ceph、Git 等也是千人量级
  • 一些专项列表可能只有几十人

列表越窄,越容易被人看到你的问题。


想贡献,不必先从「写大功能」开始

演讲给的起步顺序很务实。

1. 测 RC

主线和 stable 的 -rc 公告会发到列表。你要做的是:

  • 编译
  • 启动
  • 跑自己的工作负载或测试
  • 把结果回复到那封公告邮件里——好消息也要回

任何测试信息都有用。窗口通常只有一两天量级,动作要快。

2. 报 bug,或找已有 bug 来修

上游缺陷跟踪:https://bugzilla.kernel.org/

报 bug 本身就是贡献。描述清楚版本、复现步骤、日志和硬件,往往比丢一句「坏了」有价值得多。

3. 再考虑提交补丁

基本规矩:

  • 用 git 生成补丁
  • 一个逻辑改动对应一个补丁
  • scripts/get_maintainer.pl 找对收件人和列表
  • 邮件必须是纯文本,不要指望附件和富文本
  • 必须有 Signed-off-by(开发者来源证明)
  • 接受评审,按意见改完再投
  • 维护者很忙,至少等大约一周再 ping

完整流程写在:Submitting patches

内核社区的礼貌不是客套话,是让稀缺的评审时间用在刀刃上。


文档比想象中全

主站:https://docs.kernel.org/

同一套文档也住在源码树的 Documentation/ 里,所以不同内核版本看到的内容可能不同。优先读和你正在编译的那个版本匹配的文档。

值得先打开的几类:

  • 内核开发流程
  • 提交补丁指南
  • Code of Conduct
  • Maintainer Handbook
  • 子系统文档
  • 测试指南、hacking 指南

文档不是附录,是流程的一部分。课上的原话接近:「拿不准时,先读文档。」


一份可收藏的资源表

资源 用途
kernel.org 上游源码和版本
docs.kernel.org 官方文档
vger.kernel.org 邮件列表入口
lore.kernel.org 列表检索
kernelnewbies.org 新手社区、构建说明
bugzilla.kernel.org 报 bug、找可修的题
LTP 内核测试套件
LFD103 免费课 系统学开发流程、git、发补丁

如果这场 40 分钟的演讲是地图,LFD103 更像随身手册。


可以立刻做的五件事

  1. 打开 kernel.org,分清 Mainline、Stable、LTS。
  2. 在虚拟机里 clone 一份源码,跑一次 make menuconfig,只改一个你能理解的选项。
  3. Documentation/process/ 里和提交补丁、报告问题相关的几篇。
  4. lore.kernel.org 搜一个你感兴趣的子系统,看真实补丁长什么样。
  5. 下一次主线 -rc 出来时,编译启动一次,把结果回一封短邮件。

内核看起来像一座迷宫,其实入口很多,而且大多数入口都不要求你先成为内核黑客。先能编起来、跑起来、看懂一封补丁邮件,就已经比「收藏了十篇内核文章却从未 clone 过源码」往前走了一大步。


笔记按演讲结构重写,并补了便于实践的命令与链接。如与上游现行流程有出入,以 docs.kernel.org 当时版本为准。

发表评论: