青涩
课程
文章
工具
关于
linux内核构建流程
课程介绍
相关文章
相关视频
问答
进入linux内核源码目录
生成内核配置
make defconfig // 生成内核的默认配置
Makefile:%config
scripts/kconfig/Makefile:defconfig
scripts/kconfig/conf --defconfig=arch/x86/configs/x86_64_defconfig Kconfig
scripts/kconfig/conf.c:main // conf程序的main函数
scripts/kconfig/parser.y:conf_parse // 解析Kconfig中定义的内核配置项
scripts/kconfig/confdata.c:conf_read // 根据arch/x86/configs/x86_64_defconfig文件的内容,为对应的内核配置项赋值
scripts/kconfig/conf.c:conf_set_all_new_symbols // 对于那些还没有值的内核配置项,如果Kconfig中为其定义了默认值,则把它设置为默认值,否则设置为其类型的零值
scripts/kconfig/confdata.c:conf_write // 将最终的内核配置写到.config文件里
scripts/kconfig/confdata.c:conf_write_autoconf // 为 Makefile/c/rust 生成对应的 include/config/auto.conf, include/generated/autoconf.h, include/generated/rustc_cfg 文件
linux内核各种配置方式的区别
构建内核
make -j4 // 参数-j4表示最大允许4个任务同时运行,根据机器配置调节该参数值,当然,也可以不加这个参数
Makefile:__all // 当make没有指定构建目标时,就会执行Makefile里的第一个目标,对于linux内核来说,就是__all
Makefile:__all // 声明对all的依赖
Makefile:all // 依赖vmlinux
Makefile:vmlinux
Makefile:vmlinux.o
Makefile:vmlinux_o
Makefile:vmlinux.a
Makefile:./built-in.a lib/lib.a arch/x86/lib/lib.a
Makefile:.
Makefile:prepare
Makefile:prepare0
Makefile:archprepare
arch/x86/Makefile:archheaders
make -f ./scripts/Makefile.build obj=arch/x86/entry/syscalls all // 生成和系统调用相关的头文件,比如 arch/x86/include/generated/asm/syscalls_64.h 和 arch/x86/include/generated/uapi/asm/unistd_64.h
arch/x86/Makefile:archscripts
make -f ./scripts/Makefile.build obj=arch/x86/tools relocs // 构建 arch/x86/tools/relocs 工具
Makefile:scripts
make -f ./scripts/Makefile.build obj=scripts // 构建其他各种工具
Makefile:asm-generic
Makefile:uapi-asm-generic
make -f ./scripts/Makefile.asm-headers obj=arch/x86/include/generated/uapi/asm generic=include/uapi/asm-generic // 以 include/uapi/asm-generic 目录中的头文件为模板,生成平台通用的头文件,写到 arch/x86/include/generated/uapi/asm 目录里
make -f ./scripts/Makefile.asm-headers obj=arch/x86/include/generated/asm generic=include/asm-generic // 以 include/asm-generic 目录中的头文件为模板,生成平台通用的头文件,写到 arch/x86/include/generated/asm 目录里
make -f ./scripts/Makefile.build obj=scripts/mod // 构建 modpost 工具,这个后面会用到
make -f ./scripts/Makefile.build obj=. prepare // 生成一些头文件,比如 include/generated/asm-offsets.h
make -f ./scripts/Makefile.build obj=rust // 编译rust目录里的代码
Makefile:prepare
Makefile:tools/objtool // 构建objtool工具,该工具在内核编译过程中,有着非常重要作用
make -f ./scripts/Makefile.build obj=. need-builtin=1 need-modorder=1 // 递归构建所有目录,并在每一级目录生成 built-in.a 和 modules.order,父目录的 built-in.a 和 modules.order 包含子目录的 built-in.a 和 modules.order,另外,lib 和 arch/x86/lib 目录里还会生成 lib.a
scripts/Makefile.build:./
scripts/Makefile.build:./built-in.a // 在根目录生成 built-in.a
scripts/Makefile.build:kernel/built-in.a
scripts/Makefile.build:kernel
make -f ./scripts/Makefile.build obj=kernel need-builtin=1 need-modorder=1 // 该命令会生成 kernel/built-in.a 和 kernel/modules.order
scripts/Makefile.build:kernel/
scripts/Makefile.build:kernel/built-in.a
scripts/Makefile.build:kernel/fork.o // 由 fork.c 生成
scripts/Makefile.build:kernel/sched/built-in.a
scripts/Makefile.build:kernel/sched
make -f ./scripts/Makefile.build obj=kernel/sched need-builtin=1 need-modorder=1 // 该命令会生成 kernel/sched/built-in.a 和 kernel/sched/modules.order
scripts/Makefile.build:kernel/sched/
scripts/Makefile.build:kernel/sched/built-in.a
scripts/Makefile.build:kernel/sched/core.o // 由 core.c 生成
scripts/Makefile.build:kernel/sched/fair.o // 由 fair.c 生成
scripts/Makefile.build:kernel/sched/build_policy.o // 由 build_policy.c 生成
scripts/Makefile.build:kernel/sched/build_utility.o // 由 build_utility.c 生成
ar cDPrST kernel/sched/built-in.a kernel/sched/core.o kernel/sched/fair.o kernel/sched/build_policy.o kernel/sched/build_utility.o // 生成 kernel/sched/built-in.a
scripts/Makefile.build:kernel/sched/modules.order
{ :; } > kernel/sched/modules.order // 由于该目录下没有配置模块,所以生成的 modules.order 为空
scripts/Makefile.build:kernel/... // 其他类似,省略
ar cDPrST kernel/built-in.a kernel/fork.o kernel/sched/built-in.a ... // 生成 kernel/built-in.a
scripts/Makefile.build:kernel/modules.order
scripts/Makefile.build:kernel/sched/modules.order // 在生成 kernel/sched/built-in.a 时,同时生成了 kernel/sched/modules.order,所以这里不用再有其他操作
scripts/Makefile.build:kernel/... // 其他类似,省略
{ cat kernel/sched/modules.order; ... } > kernel/modules.order // 由于该目录及其子目录下没有配置模块,所以生成的 modules.order 为空
scripts/Makefile.build:fs/built-in.a
scripts/Makefile.build:fs
make -f ./scripts/Makefile.build obj=fs need-builtin=1 need-modorder=1 // 该命令会生成 fs/built-in.a 和 fs/modules.order
scripts/Makefile.build:fs/
scripts/Makefile.build:fs/built-in.a
scripts/Makefile.build:fs/open.o
scripts/Makefile.build:fs/ext4/built-in.a
scripts/Makefile.build:fs/... // 其他类似,省略
ar cDPrST built-in.a fs/open.o fs/ext4/built-in.a ... // 生成 built-in.a
scripts/Makefile.build:fs/modules.order
scripts/Makefile.build:fs/efivarfs/modules.order
scripts/Makefile.build:fs/efivarfs
make -f ./scripts/Makefile.build obj=fs/efivarfs need-modorder=1 // 该命令会生成 fs/efivarfs/efivarfs.o, fs/efivarfs/efivarfs.mod, fs/efivarfs/modules.order,该目录下的代码是个模块
scripts/Makefile.build:fs/efivar/
scripts/Makefile.build:fs/efivarfs/efivarfs.o
scripts/Makefile.build:fs/efivarfs/efivarfs.mod // 该文件记录了 fs/efivarfs/efivarfs.o 模块由哪些 .o 文件组成
printf 'fs/efivarfs/inode.o\nfs/efivarfs/file.o\nfs/efivarfs/super.o\nfs/efivarfs/vars.o\n' > fs/efivarfs/efivarfs.mod
ld ... -o fs/efivarfs/efivarfs.o @fs/efivarfs/efivarfs.mod // 将 fs/efivarfs/efivarfs.mod 里记录的 .o 文件,即 inode.o file.o super.o vars.o,链接成 fs/efivarfs/efivarfs.o,该命令是在这些 .o 文件生成之后才会执行
scripts/Makefile.build:fs/efivarfs/efivarfs.o
scripts/Makefile.build:fs/efivarfs/inode.o // 由 inode.c 生成
scripts/Makefile.build:fs/efivarfs/file.o // 由 file.c 生成
scripts/Makefile.build:fs/efivarfs/super.o // 由 super.c 生成
scripts/Makefile.build:fs/efivarfs/vars.o // 由 vars.c 生成
scripts/Makefile.build:fs/efivarfs/efivarfs.mod // 这个上面已经生成过了
scripts/Makefile.build:fs/efivarfs/modules.order
scripts/Makefile.build:fs/efivarfs/efivarfs.o // 这个上面已经生成过了
{ echo fs/efivarfs/efivarfs.o; :; } > fs/efivarfs/modules.order
scripts/Makefile.build:fs/... // 其他类似,省略
{ cat fs/efivarfs/modules.order; ... } > fs/modules.order
scripts/Makefile.build:lib/built-in.a
scripts/Makefile.build:lib
make -f ./scripts/Makefile.build obj=lib need-builtin=1 need-modorder=1 // 该命令会生成 lib/lib.a, lib/built-in.a, lib/modules.order,注意这里额外生成了 lib/lib.a
scripts/Makefile.build:lib/
scripts/Makefile.build:lib/lib.a // 用于生成 lib/lib.a
scripts/Makefile.build:lib/argv_split.o // 由 argv_split.c 生成
scripts/Makefile.build:lib/bug.o // 由 bug.c 生成
scripts/Makefile.build:lib/... // 其他类似,省略
ar cDPrsT lib/lib.a lib/argv_split.o lib/bug.o ... // 生成 lib/lib.a
scripts/Makefile.build:lib/built-in.a // 用于生成 lib/built-in.a,生成方式和以上描述相同
scripts/Makefile.build:lib/modules.order // 用于生成 lib/modules.order,生成方式和以上描述相同
scripts/Makefile.build:arch/x86/lib/built-in.a
scripts/Makefile.build:arch/x86/lib
make -f ./scripts/Makefile.build obj=arch/x86/lib need-builtin=1 need-modorder=1 // 该命令会生成 arch/x86/lib/lib.a, arch/x86/lib/built-in.a, arch/x86/lib/modules.order,注意这里额外生成了 arch/x86/lib/lib.a
scripts/Makefile.build:arch/x86/lib/
scripts/Makefile.build:arch/x86/lib/lib.a // 用于生成 arch/x86/lib/lib.a,生成方式和以上描述相同
scripts/Makefile.build:arch/x86/lib/built-in.a // 用于生成 arch/x86/lib/built-in.a,生成方式和以上描述相同
scripts/Makefile.build:arch/x86/lib/modules.order // 用于生成 arch/x86/lib/modules.order,生成方式和以上描述相同
scripts/Makefile.build:... // 其他类似,省略
ar cDPrST built-in.a kernel/built-in.a fs/built-in.a lib/built-in.a arch/x86/lib/built-in.a ... // 生成 built-in.a
scripts/Makefile.build:./modules.order // 在根目录生成 modules.order
scripts/Makefile.build:kernel/modules.order
scripts/Makefile.build:kernel // 在生成 kernel/built-in.a 时,已经执行过这个任务了,所以在这里,这个任务直接跳过,不用再执行了
scripts/Makefile.build:fs/modules.order // 同上
scripts/Makefile.build:lib/modules.order // 同上
scripts/Makefile.build:arch/x86/lib/modules.order // 同上
scripts/Makefile.build:... // 其他类似,省略
{ cat kernel/modules.order; cat fs/modules.order; cat lib/modules.order; cat arch/x86/lib/modules.order; ... } > modules.order // 把子目录 modules.order 的内容拼接在一起,生成当前目录的 modules.order
ar cDPrST vmlinux.a ./built-in.a lib/lib.a arch/x86/lib/lib.a // 把 built-in.a lib/lib.a arch/x86/lib/lib.a 里的内容合并在一起,生成 vmlinux.a
make -f ./scripts/Makefile.vmlinux_o // 该命令会生成 vmlinux.o, modules.builtin.modinfo, modules.builtin 文件
scripts/Makefile.vmlinux_o:__default
scripts/Makefile.vmlinux_o:vmlinux.o
vmlinux.a // 这个之前已经生成过了
ld ... -o vmlinux.o --whole-archive vmlinux.a --no-whole-archive ... // 生成 vmlinux.o
scripts/Makefile.vmlinux_o:modules.builtin.modinfo
objcopy -j .modinfo -O binary vmlinux.o modules.builtin.modinfo // 把 vmlinux.o 里的 .modinfo 这个 section 里的内容,拷贝到 modules.builtin.modinfo 文件
scripts/Makefile.vmlinux_o:modules.builtin
scripts/Makefile.vmlinux_o:modules.builtin.modinfo // 这个之前已经生成过了
tr '\0' '\n' < modules.builtin.modinfo | ... > modules.builtin // 根据 modules.builtin.modinfo 的内容,生成 modules.builtin 文件,该命令很长,这里只显示了部分,完整命令请查看内核构建时生成的 .modules.builtin.cmd 文件
Makefile:arch/x86/kernel/vmlinux.lds
Makefile:. // 这个任务之前已经执行过了,这里不用再执行,这个任务在构建 arch/x86/kernel 目录时,会生成 arch/x86/kernel/vmlinux.lds 文件
Makefile:modpost
Makefile:vmlinux.o // 这个之前已经生成过了
Makefile:modules_check
Makefile:modules.order
Makefile:. // 这个任务之前已经执行过了,这里不用再执行,它会生成 modules.order 文件
sh ./scripts/modules-check.sh modules.order // 检查是否有同名的模块,如果有就报错
make -f ./scripts/Makefile.modpost
scripts/Makefile.modpost:__modpost
scripts/Makefile.modpost:Module.symvers
./scripts/mod/modpost // 这个工具之前就生成过了
modules.order // 这个文件之前也生成过了
vmlinux.o // 这个之前也生成过了
./scripts/mod/modpost -M -o Module.symvers -T modules.order vmlinux.o // 执行 modpost 程序
make -f ./scripts/Makefile.vmlinux
arch/x86/Makefile:all // 依赖bzImage
Makefile:all // 依赖modules