整理自 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 内核,几乎都是「上游 + 本地定制」。
健康的产品策略通常是:
- 尽量把通用改动送回上游;
- 产品内核尽量贴近上游,减少自己要长期背的补丁。
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。
通用步骤
- 安装编译依赖(
gcc、make、bison、flex、libncurses等,以发行版文档为准)。 - 在源码树里执行:
make -j$(nproc)
第一次会很慢。增量编译会快很多;make clean 之后又会变慢。讲者还放了 xkcd 303:编译开始后,唯一能做的事就是去倒咖啡。
- 安装模块和内核:
sudo make modules_install
sudo make install
Ubuntu 等发行版有时要求先打成 deb 再装,不要死记这一套命令,以发行版文档为准。
- 更新 GRUB(或你正在用的引导器),重启,选新内核。
必须记住的安全网
- 至少留一个能启动的旧内核。
- 新内核坏了,机器可能直接起不来。
- 初学者请先用虚拟机。玩坏了,删掉虚机重来,不要拿日常工作电脑练手。
内核开发的第一课不是写代码,是给自己留退路。
怎么知道自己没改坏
测试方式和改动性质有关,没有万能套餐。
小改动
比如把某个变量从 u32 改成 u64:
- 加
printk - 用
dmesg看内核日志
够快,也够直观。
大改动
新功能、换内存分配器、动到全局路径,需要系统化测试。
| 工具 | 位置 | 大约耗时 | 适合什么 |
|---|---|---|---|
| LTP | 内核树外 | 全量 3–4 小时 | 稳定性、可靠性、回归 |
| kselftest | 内核树内,程序跑在用户态 | 约 20–30 分钟 | 用户态与内核交界,例如系统调用 |
经验规则:如果你加了一条新 syscall,最好同时加一条 kselftest。
开发期检查
- checkpatch:风格和常见错误。往上游发补丁前几乎人人跑。
- KASAN / KMEMLEAK 等动态工具:查越界、use-after-free、泄漏。
- ftrace、
dump_stack():看调用路径。 - objdump、addr2line、GDB:把地址翻译回源码位置。
调试资料:
上游是怎么流动的
内核不是一个仓库里所有人一起推 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
内核社区的礼貌不是客套话,是让稀缺的评审时间用在刀刃上。
文档比想象中全
同一套文档也住在源码树的 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 更像随身手册。
可以立刻做的五件事
- 打开 kernel.org,分清 Mainline、Stable、LTS。
- 在虚拟机里 clone 一份源码,跑一次
make menuconfig,只改一个你能理解的选项。 - 读
Documentation/process/里和提交补丁、报告问题相关的几篇。 - 用 lore.kernel.org 搜一个你感兴趣的子系统,看真实补丁长什么样。
- 下一次主线
-rc出来时,编译启动一次,把结果回一封短邮件。
内核看起来像一座迷宫,其实入口很多,而且大多数入口都不要求你先成为内核黑客。先能编起来、跑起来、看懂一封补丁邮件,就已经比「收藏了十篇内核文章却从未 clone 过源码」往前走了一大步。
笔记按演讲结构重写,并补了便于实践的命令与链接。如与上游现行流程有出入,以 docs.kernel.org 当时版本为准。