Eric Raymond 在《大教堂与集市》中曾言:
我认为,未来会更多地属于那些告别大教堂、拥抱集市的人们。
这不是说个人的远见和才华不再重要;而是在我看来,未来的成功者只是从自己的远见和才华开始工作,然后通过有效的社区合作,将其不断地放大。
开放式的文化会最终胜利,这或许不是因为”开放”在道德上正确,或者”封闭”在道德上错误,而只是因为开放式合作可以在一个问题上投入多几个数量级的技术工时,封闭的世界无法赢得这样的竞争。
本指南献给闯荡银河系的勇者们,愿他们也能领略到内核世界的绝美风光。
内核源码树
目录 | 内容 | 备注 |
---|---|---|
kernel | 内核核心组件 | 除非绝对必要,否则不要向该目录添加内容。 |
mm | 架构无关的内存管理代码 | |
fs | 所有文件系统实现代码 | |
init | 内核初始化相关代码 | |
ipc | 进程间通信机制 | |
block | 块设备相关代码 | |
drivers | 各类驱动程序 | 源码中所占空间最大,但只有少量成员会编译到。 |
sound | 声卡驱动程序 | 尽管有独立的目录,但和其他设备驱动程序类似。 |
net | 网络实现代码 | 包括核心和各种协议两部分。 |
lib | 通用库例程 | 包括各种数据结构和数据压缩的例程。 |
include | 所有公开导出函数的头文件 | |
usr | cpio 相关实现 | |
security | 各类安全模块 | 主要包括 LSM 模块和密钥管理代码。 |
crypto | 加密层文件 | 如各种加密算法的实现。 |
virt | 内核虚拟化代码 | |
arch | 体系结构相关文件 | 每种体系结构都有独立子目录,内部类似于顶层目录。 |
samples | 编程范例 | 包括内核和用户态编程。 |
scripts | 脚本和使用程序 | 用于编译内核、检查补丁格式等任务。 |
tools | 内核裁剪配置工具 | 将源码编译成目标文件,连接合并为可运行的 zImage。 |
Documentation | 内核文档 | 虽然其中很多过时了。 |
LICENSES | 各类相关开源许可证 | |
MAINTAINERS | 内核各模块维护者联系方式 | |
Kconfig | 编译配置文件 | 决定需要编译哪些代码。 |
Kbuild | 组件式构建配置文件 | |
Makefile | 主 Makefile | 定义 C 编译器、链接器的调用路径。 |
编译内核
Kconfig
Kbuild
内核开发
开发工作流
如何进行补丁移植
内核开发中一个常见的场景是补丁移植,将高版本内核的修复补丁或特性补丁回合到低版本内核中,往往因为补丁上下文的改动导致无法直接合入,这时候就需要我们手动进行移植。
使用
git am
尝试合入开源补丁:1
git am xxx.patch
该命令会尝试合入补丁,如果合入顺利,就直接根据补丁头的信息进行提交,如果有冲突,会回退所有的修改并告知哪里有冲突。
你可以加上
-s
选项以在提交信息中附加自己的签名。出现冲突时的处理。
首先判断冲突是否是因为补丁内容已经存在于源码中,如果是,就直接跳过补丁:
1
git am --skip
使用
git apply
合入未冲突的部分修改,并通过--reject
选项导出冲突内容到一个 .rej 文件中:1
git apply --reject xxx.patch
使用
vim -O
同时打开 .rej 文件和源文件,以便手动适配合入:1
vim -O crashfile.rej crashfile
根据补丁上下文,从 .rej 文件复制对应的修改到原文件,删除应该删除的行。
清理 .rej 文件并使用
git add
添加修改到文件,最后完成提交:1
2
3rm -f crashfile.rej
git add --all
git am --resolved
合入补丁后,根据需要补充补丁头信息:
1
git commit --amend
生成单个新补丁:
1
git format-patch --subject-prefix="PATCH version_prefix" -1
一次生成完整的补丁集:
1
git format-patch --subject-prefix="PATCH version_prefix" --cover-letter [commit-ID]
检查补丁:
1
scripts/checkpatch.pl xxx.patch
发送补丁:
1
git send-email *.patch -to "maintainer email" --cc="kernel.openeuler@huawei.com" --from="your email" --suppress-cc=all
编码风格
可移植性
内核调测
数据交互
procfs
debugfs
常规调试
printk
kprobe
SystemTap
KGDB
KGTP
崩溃调试
kdump
kdump 是一种内核崩溃转储机制,能够在系统崩溃时自动转储内存,以用于后续分析。
kdump 工作过程如下:
系统内核启动的时候,为 capture 内核预留一块内存空间,该空间无法被当前内核访问;
这块空间的大小及其在内存中的偏移可通过启动参数中的
crashkernel=size[@offset]
指定。内核启动完成后,kdump 服务执行
kexec -p
把 capture 内核载入预留的内存;如果当前内核发生崩溃,就自动把控制权交给 capture 内核(capture 内核仅使用预留内存,因此其余内存数据不会被改动),由该内核把崩溃内核内存中的数据写入到 dump 文件;
写完 dump 文件中,capture 内核自动重启。
这里不过多介绍 kdump 的设置,读者可以在各发行版的文档中找到(例如红帽),直接介绍如何通过 vmcore 文件获取系统崩溃信息。
SysRq 魔术键
性能调优
perf
性能分析的“瑞士军刀”。
总结
参考资料
变更记录
- 2020.11.25:完成目录框架。
- Post title:内核漫游指南
- Post author:Anakin
- Create time:2020-11-25 08:35:22
- Post link:https://nettingsisyphus.tech/2020/11/25/kernel-diving-guide/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.