《Linux内核源码全景解读:从上电到用户态》
-
- 一、全书结构
- [二、上篇目录:按 x86_64 启动阶段划分](#二、上篇目录:按 x86_64 启动阶段划分)
-
- [第 1 章 上电、固件与 x86_64 启动契约](#第 1 章 上电、固件与 x86_64 启动契约)
- [第 2 章 实模式 setup:从 boot sector 到 protected mode](#第 2 章 实模式 setup:从 boot sector 到 protected mode)
- [第 3 章 压缩内核入口:临时页表与解压执行环境](#第 3 章 压缩内核入口:临时页表与解压执行环境)
- [第 4 章 跳入解压后的内核:`startup_64` 与初始身份映射](#第 4 章 跳入解压后的内核:
startup_64与初始身份映射) - [第 5 章 `x86_64_start_kernel()`:进入通用内核前的架构收口](#第 5 章
x86_64_start_kernel():进入通用内核前的架构收口) - [第 6 章 `start_kernel()` 总览:内核生命线的主函数](#第 6 章
start_kernel()总览:内核生命线的主函数) - [第 7 章 `setup_arch()`:x86_64 拓扑、内存图与平台发现](#第 7 章
setup_arch():x86_64 拓扑、内存图与平台发现) - [第 8 章 早期内存管理:memblock、页表与伙伴系统前夜](#第 8 章 早期内存管理:memblock、页表与伙伴系统前夜)
- [第 9 章 异常、IRQ 与时间:内核获得外部世界的节拍](#第 9 章 异常、IRQ 与时间:内核获得外部世界的节拍)
- [第 10 章 调度器、RCU 与并发基础设施](#第 10 章 调度器、RCU 与并发基础设施)
- [第 11 章 控制台、printk 与可观测启动](#第 11 章 控制台、printk 与可观测启动)
- [第 12 章 进程模型成形:fork、pid、cred 与 `rest_init()`](#第 12 章 进程模型成形:fork、pid、cred 与
rest_init()) - [第 13 章 VFS 与根文件系统前置:从 dcache 到 initramfs](#第 13 章 VFS 与根文件系统前置:从 dcache 到 initramfs)
- [第 14 章 安全与命名空间:用户态边界的形成](#第 14 章 安全与命名空间:用户态边界的形成)
- [第 15 章 initcall 机制:驱动、总线、文件系统与网络的批量唤醒](#第 15 章 initcall 机制:驱动、总线、文件系统与网络的批量唤醒)
- [第 16 章 挂载根文件系统与执行 `/sbin/init`](#第 16 章 挂载根文件系统与执行
/sbin/init)
- 三、下篇目录:核心子系统深度剖析
-
- [第 17 章 调度子系统:从 `rq` 到 EEVDF](#第 17 章 调度子系统:从
rq到 EEVDF) - [第 18 章 内存管理:从 memblock 到 folio/Maple Tree](#第 18 章 内存管理:从 memblock 到 folio/Maple Tree)
- [第 19 章 VFS 与文件系统:路径、对象与页缓存](#第 19 章 VFS 与文件系统:路径、对象与页缓存)
- [第 20 章 网络子系统:从 `sk_buff` 到 `net_device`](#第 20 章 网络子系统:从
sk_buff到net_device) - [第 21 章 进程间通信(IPC):信号量、消息队列与共享内存](#第 21 章 进程间通信(IPC):信号量、消息队列与共享内存)
- [第 22 章 RCU 与同步原语:读多写少世界的基础设施](#第 22 章 RCU 与同步原语:读多写少世界的基础设施)
- [第 23 章 块层与 I/O:bio、request 与 blk-mq](#第 23 章 块层与 I/O:bio、request 与 blk-mq)
- [第 24 章 设备模型、驱动核心与电源管理](#第 24 章 设备模型、驱动核心与电源管理)
- [第 25 章 安全子系统:LSM、凭据与系统调用边界](#第 25 章 安全子系统:LSM、凭据与系统调用边界)
- [第 26 章 cgroup、namespace 与容器基础设施](#第 26 章 cgroup、namespace 与容器基础设施)
- [第 27 章 eBPF、 tracing 与可观测性](#第 27 章 eBPF、 tracing 与可观测性)
- [第 28 章 模块、符号与内核扩展边界](#第 28 章 模块、符号与内核扩展边界)
- [第 17 章 调度子系统:从 `rq` 到 EEVDF](#第 17 章 调度子系统:从
- [四、时序全景图描述:从 `start_kernel()` 到 `do_initcalls()`](#四、时序全景图描述:从
start_kernel()到do_initcalls())
版本口径:本目录基于本地源码树 linux-7.1.3,架构范围限定为 x86_64。本文档按实际源码 Linux 7.1.3 组织路径与章节。
核心叙事:全书以 "上电 -> BIOS/UEFI -> 引导协议 -> 解压内核 -> x86_64 早期入口 -> start_kernel() -> initcall -> rootfs/init -> 用户态" 为主线。上篇按启动时序唤醒子系统,下篇再把这些子系统拆开深挖。
一、全书结构
上篇:启动时序篇
目标是按时间顺序回答 "内核怎样从一段不可调度、不可分页、不可中断的早期代码,逐步成长为能创建进程、挂载根文件系统、加载驱动并进入用户态的系统"。每章都绑定一个启动阶段,并说明该阶段首次引出的子系统。
下篇:子系统深度篇
目标是把上篇中被依次唤醒的核心子系统独立展开:数据结构、关键算法、热路径、初始化入口、调试观察点,以及从 Linux 5.12 到本源码 7.1.3 的主要演进线索。
二、上篇目录:按 x86_64 启动阶段划分
第 1 章 上电、固件与 x86_64 启动契约
- 启动阶段:CPU reset vector、BIOS/UEFI 固件、bootloader 交接。
- 引入子系统:x86 boot protocol、boot params、命令行、E820/EFI 内存图。
- 核心源码路径:
Documentation/arch/x86/boot.rst、arch/x86/include/uapi/asm/bootparam.h、arch/x86/include/asm/e820/types.h、arch/x86/platform/efi/efi.c。 - 叙事重点:内核并不是从 C 语言
main()开始,而是从固件和引导器约定的数据结构开始。
第 2 章 实模式 setup:从 boot sector 到 protected mode
- 启动阶段:x86 setup code 接管 bootloader 传入的参数。
- 引入子系统:早期控制台、A20、CPU 特性探测、视频模式、命令行解析。
- 核心源码路径:
arch/x86/boot/header.S、arch/x86/boot/main.c、arch/x86/boot/boot.h、arch/x86/boot/cmdline.c、arch/x86/boot/cpu.c、arch/x86/boot/pm.c。 - 叙事重点:为什么早期代码有自己的 tiny libc、printf、BIOS 调用封装,以及它如何准备进入保护模式。
第 3 章 压缩内核入口:临时页表与解压执行环境
- 启动阶段:进入
arch/x86/boot/compressed/,建立解压用的最小运行时。 - 引入子系统:KASLR、早期页表、早期异常处理、早期串口/控制台。
- 核心源码路径:
arch/x86/boot/compressed/head_64.S、arch/x86/boot/compressed/misc.c、arch/x86/boot/compressed/kaslr.c、arch/x86/boot/compressed/pgtable_64.c、arch/x86/boot/compressed/error.c。 - 叙事重点:
startup_32/startup_64如何调用extract_kernel(),并返回真正内核映像入口。
第 4 章 跳入解压后的内核:startup_64 与初始身份映射
- 启动阶段:解压后的 vmlinux 从汇编入口建立 long mode 所需状态。
- 引入子系统:GDT/IDT、early page table、内核虚拟地址、SME/SEV 内存加密准备。
- 核心源码路径:
arch/x86/kernel/head_64.S、arch/x86/kernel/head64.c、arch/x86/boot/startup/map_kernel.c、arch/x86/boot/startup/gdt_idt.c、arch/x86/mm/mem_encrypt.c。 - 叙事重点:
startup_64 -> common_startup_64 -> x86_64_start_kernel()如何把执行权移交给 C 层。
第 5 章 x86_64_start_kernel():进入通用内核前的架构收口
- 启动阶段:x86_64 C 入口完成 early IDT、清 BSS、CPU 基础状态和命令行承接。
- 引入子系统:early IDT、ORC/unwind 准备、early fixmap、静态分支基础。
- 核心源码路径:
arch/x86/kernel/head64.c、arch/x86/kernel/head_64.S、arch/x86/kernel/cpu/common.c、arch/x86/include/asm/setup.h。 - 叙事重点:为何
start_kernel()是通用内核入口,但它不是机器真正执行的第一段内核代码。
第 6 章 start_kernel() 总览:内核生命线的主函数
- 启动阶段:进入
init/main.c:start_kernel()。 - 引入子系统:lockdep、boot CPU、静态 key、cgroup 早期初始化、调试对象、栈随机化。
- 核心源码路径:
init/main.c、include/linux/start_kernel.h、kernel/locking/lockdep.c、kernel/cgroup/cgroup.c、lib/debugobjects.c。 - 叙事重点:把
start_kernel()拆成 "架构感知、内存可用、调度可用、中断可用、VFS 可用、用户态可用" 六段。
第 7 章 setup_arch():x86_64 拓扑、内存图与平台发现
- 启动阶段:
start_kernel()调用setup_arch(&command_line)。 - 引入子系统:E820/memblock、NUMA、ACPI、EFI、CPU feature、KASLR 结果固化、early ioremap。
- 核心源码路径:
arch/x86/kernel/setup.c、arch/x86/kernel/e820.c、arch/x86/mm/init.c、arch/x86/mm/init_64.c、arch/x86/mm/numa.c、arch/x86/kernel/acpi/boot.c、arch/x86/platform/efi/efi.c。 - 叙事重点:所有后续内存管理、设备枚举和 SMP 初始化都依赖
setup_arch()建立的平台事实。
第 8 章 早期内存管理:memblock、页表与伙伴系统前夜
- 启动阶段:
setup_arch()后到mm_core_init()前后。 - 引入子系统:memblock、sparsemem、page allocator、SLUB、vmalloc、percpu allocator。
- 核心源码路径:
mm/mm_init.c、mm/memblock.c、mm/page_alloc.c、mm/sparse.c、mm/slub.c、mm/vmalloc.c、mm/percpu.c、include/linux/mmzone.h。 - 叙事重点:从固件内存图到
struct page,再到早期分配器被正式页分配器接管。
第 9 章 异常、IRQ 与时间:内核获得外部世界的节拍
- 启动阶段:
trap_init()、init_IRQ()、tick_init()、timekeeping_init()。 - 引入子系统:IDT、异常处理、irqdesc、APIC/IO-APIC、clocksource、tick、timer wheel/hrtimer。
- 核心源码路径:
arch/x86/kernel/traps.c、arch/x86/kernel/idt.c、arch/x86/kernel/irqinit.c、kernel/irq/irqdesc.c、kernel/time/tick-common.c、kernel/time/timekeeping.c、kernel/time/hrtimer.c。 - 叙事重点:没有中断和时钟,调度器只能初始化,无法成为真正的多任务系统。
第 10 章 调度器、RCU 与并发基础设施
- 启动阶段:
sched_init()、rcu_init()、srcu_init()、softirq/tasklet/workqueue 准备。 - 引入子系统:CFS/EEVDF、RT/DL、sched class、RCU tree、SRCU、softirq、workqueue。
- 核心源码路径:
kernel/sched/core.c、kernel/sched/fair.c、kernel/sched/rt.c、kernel/sched/deadline.c、kernel/rcu/tree.c、kernel/rcu/srcutree.c、kernel/softirq.c、kernel/workqueue.c。 - 叙事重点:调度器和 RCU 是大量后续子系统的隐形前置条件。
第 11 章 控制台、printk 与可观测启动
- 启动阶段:
console_init()前后的 early console 到正式 console 切换。 - 引入子系统:printk ring buffer、console driver、earlycon、fbcon/tty console。
- 核心源码路径:
kernel/printk/printk.c、include/linux/console.h、drivers/tty/tty_io.c、drivers/video/fbdev/core/fbcon.c、arch/x86/boot/early_serial_console.c。 - 叙事重点:日志可见性本身也是一个逐步初始化的子系统。
第 12 章 进程模型成形:fork、pid、cred 与 rest_init()
- 启动阶段:
fork_init()、proc_caches_init()、rest_init()创建kernel_init和 kthreadd。 - 引入子系统:task_struct、pid、cred、signal、kthread、init_task。
- 核心源码路径:
kernel/fork.c、init/init_task.c、kernel/pid.c、kernel/cred.c、kernel/kthread.c、include/linux/sched.h、include/linux/pid.h。 - 叙事重点:0 号进程如何分裂出 1 号内核线程路径和 2 号 kthreadd。
第 13 章 VFS 与根文件系统前置:从 dcache 到 initramfs
- 启动阶段:
vfs_caches_init()、mnt_init()、init_rootfs()、initramfs 解包。 - 引入子系统:VFS、dcache、inode cache、mount namespace、rootfs、initramfs。
- 核心源码路径:
fs/dcache.c、fs/inode.c、fs/file_table.c、fs/namespace.c、fs/filesystems.c、init/initramfs.c、init/do_mounts.c。 - 叙事重点:进入用户态前,内核必须先有 "路径、文件、挂载点、根" 的抽象。
第 14 章 安全与命名空间:用户态边界的形成
- 启动阶段:
early_security_init()、security_init()、namespace 与 keyring 等初始化。 - 引入子系统:LSM、capability、cred、user namespace、pid/mount/net namespace、audit。
- 核心源码路径:
security/security.c、security/commoncap.c、security/lsm_init.c、kernel/user_namespace.c、kernel/nsproxy.c、kernel/audit.c。 - 叙事重点:用户态不是 "自然可信" 的目标,而是受凭据、命名空间和 LSM 策略约束的执行环境。
第 15 章 initcall 机制:驱动、总线、文件系统与网络的批量唤醒
- 启动阶段:
kernel_init_freeable()调用do_basic_setup(),随后do_initcalls()。 - 引入子系统:initcall 分层、driver core、bus/class/device、PCI/ACPI、网络协议栈、块层、文件系统注册。
- 核心源码路径:
init/main.c、include/linux/init.h、drivers/base/init.c、drivers/pci/pci.c、net/core/dev.c、net/ipv4/af_inet.c、block/blk-core.c、fs/filesystems.c。 - 叙事重点:
pure -> core -> postcore -> arch -> subsys -> fs -> rootfs -> device -> late不是简单列表,而是依赖排序协议。
第 16 章 挂载根文件系统与执行 /sbin/init
- 启动阶段:
prepare_namespace()、init_mount_tree()、run_init_process()。 - 引入子系统:root device、block layer、filesystem probing、execve、binfmt_elf、动态链接器入口。
- 核心源码路径:
init/do_mounts.c、init/do_mounts_initrd.c、init/do_mounts_rd.c、fs/exec.c、fs/binfmt_elf.c、fs/open.c、block/blk-core.c。 - 叙事重点:内核启动主线的终点不是 shell,而是成功把 PID 1 的控制权交给用户态 init。
三、下篇目录:核心子系统深度剖析
第 17 章 调度子系统:从 rq 到 EEVDF
- 核心数据结构:
struct task_struct、struct rq、struct cfs_rq、struct sched_entity、struct sched_class、struct sched_dl_entity、struct rt_rq。 - 核心源码路径:
include/linux/sched.h、kernel/sched/sched.h、kernel/sched/core.c、kernel/sched/fair.c、kernel/sched/rt.c、kernel/sched/deadline.c、kernel/sched/ext.c。 - 核心算法:调度类链、唤醒抢占、负载均衡、CFS/EEVDF 虚拟截止时间、RT 优先级队列、deadline CBS、CPU affinity、NUMA balancing。
- 5.12 到 7.1.3 演进关键点:CFS 从 vruntime 红黑树模型演进到 EEVDF 语义;调度扩展
sched_ext进入源码;PREEMPT_DYNAMIC/PREEMPT_RT 相关路径更完整;utilization clamping、energy-aware scheduling 和 PSI 观测继续深化。
第 18 章 内存管理:从 memblock 到 folio/Maple Tree
- 核心数据结构:
struct page、struct folio、struct zone、struct pglist_data、struct mm_struct、struct vm_area_struct、struct maple_tree、struct address_space。 - 核心源码路径:
mm/mm_init.c、mm/page_alloc.c、mm/memory.c、mm/mmap.c、mm/vmscan.c、mm/huge_memory.c、mm/slub.c、include/linux/mm_types.h、include/linux/maple_tree.h。 - 核心算法:伙伴系统、per-cpu page list、SLUB 分配、页表缺页处理、匿名/文件页回收、LRU/MGLRU、THP、NUMA policy、GUP、COW。
- 5.12 到 7.1.3 演进关键点:folio 成为页缓存和复合页处理的中心抽象;VMA 管理从红黑树迁移到 Maple Tree;MGLRU、DAMON、mseal、large folio/mTHP 相关路径显著扩展;内存热插拔、memcg、KASAN/KMSAN 支撑增强。
第 19 章 VFS 与文件系统:路径、对象与页缓存
- 核心数据结构:
struct inode、struct dentry、struct super_block、struct file、struct mount、struct file_system_type、struct address_space。 - 核心源码路径:
fs/dcache.c、fs/inode.c、fs/namei.c、fs/namespace.c、fs/super.c、fs/file_table.c、fs/read_write.c、mm/filemap.c。 - 核心算法:路径解析、dcache lookup、RCU-walk/ref-walk、挂载传播、page cache read/write、writeback、文件锁、splice/direct I/O。
- 5.12 到 7.1.3 演进关键点:mount API 和 fs_context 更成熟;pidfs 等新型伪文件系统进入主线;folio 化深入页缓存和网络文件系统;io_uring 与文件/块设备路径耦合更深;idmapped mounts 与命名空间边界继续扩展。
第 20 章 网络子系统:从 sk_buff 到 net_device
- 核心数据结构:
struct sk_buff、struct net_device、struct sock、struct socket、struct proto、struct napi_struct、struct net、struct dst_entry。 - 核心源码路径:
net/core/dev.c、net/core/skbuff.c、net/socket.c、net/ipv4/af_inet.c、net/ipv4/ip_input.c、net/ipv4/tcp*.c、net/ipv6/、include/linux/netdevice.h、include/linux/skbuff.h。 - 核心算法:NAPI poll、GRO/GSO、qdisc、routing lookup、TCP 拥塞控制、socket receive/send buffer、net namespace、XDP/eBPF hook。
- 5.12 到 7.1.3 演进关键点:XDP、BPF、AF_XDP 和 tc hook 生态继续扩大;MPTCP 更成熟;netmem/page_pool、GRO 和零拷贝路径强化;网络命名空间、nftables、TLS offload 等路径继续增长。
第 21 章 进程间通信(IPC):信号量、消息队列与共享内存
- 核心数据结构:
struct sem_array、struct msg_queue、struct shmid_kernel、struct ipc_ids、struct kern_ipc_perm。 - 核心源码路径:
ipc/sem.c、ipc/msg.c、ipc/shm.c、ipc/util.c、ipc/mqueue.c、include/linux/ipc.h、include/uapi/linux/sem.h、include/uapi/linux/msg.h、include/uapi/linux/shm.h。 - 核心算法:System V 信号量原子操作与 undo、消息队列类型匹配和阻塞唤醒、共享内存
shmget -> shmat映射、IPC_RMID延迟删除、POSIX mqueue 通知。 - 5.12 到 7.1.3 演进关键点:IPC namespace 与 nsfs 视角继续完善;共享内存和 tmpfs、memcg、页表管理联系更紧;权限检查、LSM hook 和容器边界持续强化。
第 22 章 RCU 与同步原语:读多写少世界的基础设施
- 核心数据结构:
struct rcu_head、struct rcu_state、struct rcu_node、struct rcu_data、struct srcu_struct、struct lock_class_key。 - 核心源码路径:
kernel/rcu/tree.c、kernel/rcu/srcutree.c、kernel/rcu/tasks.h、include/linux/rcupdate.h、include/linux/srcu.h、kernel/locking/。 - 核心算法:grace period 检测、quiescent state、callback offload、RCU Tasks、SRCU per-domain grace period、lockdep 验证、seqlock、percpu rwsem。
- 5.12 到 7.1.3 演进关键点:Tasks RCU、Lazy RCU callback、nocb/offload 与能耗优化持续演进;SRCU 和 sleepable RCU 使用面扩大;PREEMPT_RT 迫使更多同步原语明确区分 raw spinlock、spinlock 和睡眠锁。
第 23 章 块层与 I/O:bio、request 与 blk-mq
- 核心数据结构:
struct bio、struct request、struct request_queue、struct gendisk、struct blk_mq_hw_ctx、struct blk_mq_tag_set、struct elevator_queue。 - 核心源码路径:
block/blk-core.c、block/blk-mq.c、block/blk-mq-sched.c、block/bio.c、block/genhd.c、block/elevator.c、include/linux/blk_types.h、include/linux/blk-mq.h。 - 核心算法:bio 合并、request 分发、tag 分配、multi-queue 映射、I/O scheduler、writeback throttling、blk-cgroup、flush/FUA。
- 5.12 到 7.1.3 演进关键点:blk-mq 已成为中心路径;io_uring command 与块设备接口结合更紧;BFQ、mq-deadline、wbt、blk-cgroup 延迟控制持续调整;folio 化影响文件系统到 bio 的页提交路径。
第 24 章 设备模型、驱动核心与电源管理
- 核心数据结构:
struct device、struct device_driver、struct bus_type、struct class、struct kobject、struct kset、struct dev_pm_ops。 - 核心源码路径:
drivers/base/core.c、drivers/base/bus.c、drivers/base/dd.c、drivers/base/class.c、drivers/base/power/、lib/kobject.c、include/linux/device.h。 - 核心算法:device/driver match、probe/remove、deferred probe、sysfs/kobject 生命周期、runtime PM、system suspend/resume、device links。
- 5.12 到 7.1.3 演进关键点:fw_devlink、deferred probe、device links 和 runtime PM 关系更紧;CXL、PCIe、ACPI/DT 平台发现规模扩大;sysfs 属性生命周期和 Rust/auxiliary bus 等新驱动组织方式影响驱动模型边界。
第 25 章 安全子系统:LSM、凭据与系统调用边界
- 核心数据结构:
struct cred、struct user_namespace、struct linux_binprm、struct lsm_blob_sizes、struct security_hook_list、kernel_cap_t。 - 核心源码路径:
security/security.c、security/lsm_init.c、security/commoncap.c、kernel/cred.c、kernel/user_namespace.c、fs/exec.c、include/linux/lsm_hooks.h、include/linux/cred.h。 - 核心算法:cred copy-on-write、capability 检查、LSM hook 分发、exec 凭据提交、seccomp 过滤、keyring、audit。
- 5.12 到 7.1.3 演进关键点:LSM stacking 与 blob 管理继续强化;Landlock、IMA/EVM、BPF LSM 等可组合安全机制扩展;用户命名空间和 idmapped mount 使权限判断更依赖上下文。
第 26 章 cgroup、namespace 与容器基础设施
- 核心数据结构:
struct cgroup、struct cgroup_subsys_state、struct css_set、struct nsproxy、struct pid_namespace、struct mnt_namespace、struct net。 - 核心源码路径:
kernel/cgroup/cgroup.c、kernel/cgroup/、kernel/nsproxy.c、kernel/pid_namespace.c、fs/namespace.c、net/core/net_namespace.c、include/linux/cgroup.h。 - 核心算法:css 生命周期、rstat 刷新、cgroup v2 层级控制、cpu/memory/io controller、namespace clone/unshare/setns、pidfd。
- 5.12 到 7.1.3 演进关键点:cgroup v2 成为事实主线;rstat、pressure stall information 和 BPF-cgroup hook 更重要;pidfd/pidfs 让进程引用模型更文件描述符化;容器边界越来越多由 VFS、LSM、namespace 协同表达。
第 27 章 eBPF、 tracing 与可观测性
- 核心数据结构:
struct bpf_prog、struct bpf_map、struct bpf_verifier_env、struct trace_event_call、struct ftrace_ops、struct perf_event。 - 核心源码路径:
kernel/bpf/、kernel/trace/、kernel/events/core.c、include/linux/bpf.h、include/linux/trace_events.h、arch/x86/net/bpf_jit_comp.c。 - 核心算法:BPF verifier、JIT、map 生命周期、kprobe/uprobe、ftrace 动态改写、perf ring buffer、tracepoint、BTF/CO-RE。
- 5.12 到 7.1.3 演进关键点:BPF 子系统从观测工具扩展为网络、安全、调度、cgroup 的可编程平面;BTF、kfunc、struct_ops、sleepable BPF、token/delegation 等机制扩大了受控扩展能力。
第 28 章 模块、符号与内核扩展边界
- 核心数据结构:
struct module、struct kernel_symbol、struct modversion_info、struct jump_entry、struct static_key。 - 核心源码路径:
kernel/module/、kernel/kallsyms.c、kernel/jump_label.c、include/linux/module.h、include/linux/jump_label.h。 - 核心算法:ELF section 装载、重定位、符号解析、module init/exit、livepatch 约束、static branch patching。
- 5.12 到 7.1.3 演进关键点:模块代码拆分到
kernel/module/更清晰;签名、BTF、livepatch、static call/static key 与可观测性工具耦合更强;Rust 模块支持改变了扩展边界的语言假设。
四、时序全景图描述:从 start_kernel() 到 do_initcalls()
这幅图建议画成一条横向时间轴,左侧是 x86_64_start_kernel(),中间是 start_kernel(),右侧是 kernel_init_freeable() 和 do_initcalls()。时间轴下方用分层泳道表示子系统依赖。
-
第一段是 "架构事实层"。
x86_64_start_kernel()将汇编早期状态收口后进入start_kernel();setup_arch()读取 boot params、E820/EFI、ACPI、CPU feature、NUMA 拓扑,并用 memblock 描述可用物理内存。图上应把它标成所有后续子系统的底座。 -
第二段是 "内存可分配层"。
mm_core_init()之后,struct page、zone、伙伴系统、SLUB、vmalloc、percpu allocator 逐步可用。依赖箭头从这里指向调度器、VFS、网络、驱动核心,因为这些子系统都需要稳定的动态内存分配。 -
第三段是 "执行与同步层"。
sched_init()初始化 runqueue、调度类和 idle 任务语义;rcu_init()、srcu_init()让读多写少同步机制可用;softirq/workqueue 等异步执行基础随后具备条件。图上应把 RCU 画成横贯 VFS、网络、设备模型、文件描述符表的共享依赖。 -
第四段是 "外部事件层"。
trap_init()、init_IRQ()、tick_init()、timekeeping_init()让异常、中断和时间源进入工作状态。箭头应从 IRQ/time 指向调度抢占、timer、hrtimer、网络 NAPI、块层超时、RCU grace period 推进。 -
第五段是 "对象模型层"。
fork_init()、proc_caches_init()让task_struct、pid、cred 等进程对象可规模化分配;vfs_caches_init()让 dentry、inode、file、mount 等 VFS 对象可用;security_init()把 LSM hook 接入执行、文件和网络路径。图上应把进程、VFS、安全三者画成进入用户态前的三角门槛。 -
第六段是 "第一个并发分叉"。
rest_init()创建kernel_init和kthreadd。原始 boot CPU 进入 idle 路径,kernel_init继续完成可释放初始化,kthreadd成为后续内核线程的父进程。图上这里应画出主线从start_kernel()分叉:一支到 idle,一支到 PID 1 的内核态准备,一支到 PID 2 的内核线程服务。 -
第七段是 "批量唤醒层"。
kernel_init_freeable()调用do_basic_setup(),再调用do_initcalls()。initcall 层级从pure、core、postcore、arch、subsys、fs、rootfs、device到late,依次唤醒驱动核心、总线、文件系统、网络协议、块设备、平台设备和 late init 任务。图上应把 initcall 画成阶梯,而不是并列队列。 -
第八段是 "用户态交接层"。initcall 完成后,
prepare_namespace()挂载根文件系统,run_init_process()尝试/sbin/init、/etc/init、/bin/init、/bin/sh等路径。箭头从 VFS、块层、文件系统、LSM、exec/binfmt 汇聚到 PID 1 的execve,表示内核启动叙事在这里切换到用户态启动叙事。
整体依赖关系可以概括为:架构发现决定内存边界;内存分配支撑一切对象;调度、RCU、中断和时间让对象能并发运行;VFS、安全和进程模型定义用户态入口;initcall 机制按依赖层级批量唤醒可插拔子系统;最后根文件系统和 execve 把 PID 1 送入用户态。