🔨 整理中 · 这一篇深入讲 Kbuild(内核构建系统)——内核怎么从上万源文件 + 配置,编出一个内核镜像 + 一堆模块。03 编译内核 里我们
make过,这边拆obj-y/m怎么决定编什么、vmlinux 怎么链接成Image、模块怎么变.ko。
做什么
内核源码上万 .c,怎么知道哪些编进内核镜像、哪些编成模块、怎么链接成最终的 Image?答案是 Kbuild——内核自己的 Makefile 框架。它用 obj-y/obj-m 这些约定变量告诉系统"编哪些",用 scripts/Makefile.build 等脚本驱动 gcc/ld 实际编译,最后链接 + 压缩出 arch/<arch>/boot/Image。这一篇拆 Kbuild 的几个关键约定,让你读得懂内核各目录的 Makefile。
要了解什么
一、obj-y / obj-m / obj-n:编什么、怎么编
每个目录的 Makefile 用 obj-* 变量声明"本目录产出什么":
obj-y += foo.o:把foo.c编进内核镜像(built-in,yes)。obj-y链进 vmlinux。obj-m += foo.o:编成模块foo.ko(可加载)。obj-n(不编)基本不写(默认就是不编)。
obj-$(CONFIG_FOO) 是常见写法——Kconfig 选项 CONFIG_FOO 是 y/m/空,直接拼成 obj-y/obj-m/无,这样配置选项和"编不编、怎么编"自动联动。
二、多文件聚合:foo-y / foo-objs
一个目标 foo 由多个 .c 组成时:obj-m += foo.o + foo-y := a.o b.o c.o(或老写法 foo-objs),Kbuild 把 a/b/c 编出 .o、链接成 foo.o、最后 foo.ko。这就是 模块参数 那篇提过的"链接多源文件模拟库"的底层。
三、core-y / libs-y / drivers-y:顶层目录收集
顶层 Makefile(Makefile:792 core-y := 附近)用 core-y/libs-y/drivers-y/net-y 这些变量收集"哪些顶层目录的 built-in 要链进 vmlinux"——init/ kernel/ mm/ fs/ ipc/ security/ 进 core-y,drivers/ 进 drivers-y 等。各子目录的 obj-y 产物汇总到 built-in.a,最后链接成 vmlinux。
四、链接链:.c → .o → built-in.a → vmlinux → Image
gcc把每个.c编成.o。ar把各目录的obj-y产物归档成built-in.a(每目录一个)。- 上层再归档,最终
vmlinux.a(Makefile:1253 vmlinux.a:)。 ld链接vmlinux.a+ 库 →vmlinux(Makefile:1274 vmlinux:)——这是带调试符号的完整内核 ELF。objcopy把vmlinux的.text/.data/.bss提取 + 压缩(gzip/lz4/xz) →arch/<arch>/boot/Image(ARM64)或bzImage(x86)——这是引导加载器加载的内核镜像。
五、模块:.ko 怎么来
make modules 编所有 obj-m。每个模块:.c → .o → .mod.c(Kbuild 生成的元数据文件,含 struct module 实例 + vermagic)→ 链接成 foo.ko。.ko 是特殊 ELF(带 .modinfo 段存 license/param/vermagic、.gnu.linkonce.this_module 段存 module 结构)。insmod 加载它。详见 07 模块/09 模块参数。
动手试试
- 读
Makefile顶层(core-y/libs-y/vmlinux:等规则)+scripts/Makefile.build(obj-$ 怎么被处理) - 读
drivers/char/Makefile看一个目录的obj-$(CONFIG_*) += *.o实例 make ARCH=arm64 V=1 Image打印实际命令,看 gcc/ar/ld/objcopy 链条ls -l vmlinux arch/arm64/boot/Image,对比两者(vmlinux 巨大带符号、Image 小且压缩)- 思考题:
vmlinux(ELF)和Image(引导镜像)为什么要分两个?(提示:引导加载器格式 + 体积 + 调试符号)
延伸阅读
- 源码(本仓库
third_party/linux/,6.19.9):顶层Makefile(core-y :792/vmlinux :1274/vmlinux.a :1253);scripts/Makefile.build(obj-$处理)、scripts/Makefile.modfinal(模块链接);Documentation/kbuild/各专题(makefiles.rst/modules.rst)。 - 关联本站:03 编译内核 实战、14 Kconfig 配置系统、07 模块
.ko机制;本站scripts/linux-action-scripts.sh封装了编译流程。 - 读书笔记:ch03 讲内核构建。