Linux内核分析之基础知识-5

韩乔落

第5章:通用启动流程 start_kernel

所有架构的 C 语言初始化入口


本章概述

start_kernel() 是 Linux 内核的通用 C 语言入口点,所有架构最终都会跳转到这个函数。本章详细讲解这个核心初始化函数的执行流程。

start_kernel 调用链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─────────────────────────────────────────────────────────────┐
│ start_kernel() 调用流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ startup_64() / __primary_switch() │
│ │ │
│ ↓ │
│ start_kernel() ────────────────────────┐ │
│ │ │ │
│ ├─ setup_arch() │ │
│ ├─ trap_init() │ │
│ ├─ mm_core_init() │ │
│ ├─ sched_init() │ │
│ ├─ early_irq_init() │ │
│ ├─ init_IRQ() │ │
│ ├─ console_init() │ │
│ ├─ security_init() │ │
│ └─ rest_init() │ │
│ │ │ │
│ ├─ rcu_scheduler_starting()│ │
│ ├─ kernel_init() ────────┐│ │
│ │ │ └─ do_initcalls() │
│ │ └─ run_init_process() │
│ └─ kthreadd() │
│ │
└─────────────────────────────────────────────────────────────┘

5.1 start_kernel 入口

5.1.1 函数定义和初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* init/main.c */

asmlinkage __visible __init __no_sanitize_address __noreturn __no_stack_protector
void start_kernel(void)
{
char *command_line;
char *after_dashes;

/*
* 初始化任务栈
* 设置栈魔数以检测栈溢出
*/
set_task_stack_end_magic(&init_task);

/*
* 设置处理器 ID
* SMP 系统中初始化 CPU 编号
*/
smp_setup_processor_id();

/*
* 早期调试对象初始化
*/
debug_objects_early_init();

/*
* 初始化构建 ID
* 用于唯一标识内核构建
*/
init_vmlinux_build_id();

/* ... 更多初始化 ... */
}

5.1.2 栈魔数机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 内核栈魔数定义 */
#define STACK_END_MAGIC 0x57AC6E9D

void set_task_stack_end_magic(struct task_struct *task)
{
unsigned long *stackend;

/* 栈的底部位置 */
stackend = end_of_stack(task);

/* 设置魔数 */
*stackend = STACK_END_MAGIC;

/*
* 当栈增长到这个位置时, 魔数会被覆盖
* 可以通过检查魔数来检测栈溢出
*/
}

/* 检查栈溢出 */
static inline int stack_is_overflowed(struct thread_info *ti)
{
return ti->stack_canary != STACK_END_MAGIC;
}

5.2 早期初始化

5.2.1 完整的早期初始化序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
void start_kernel(void)
{
/* ... 前面的初始化 ... */

/*
* Cgroup 早期初始化
* 必须在内存分配之前完成
*/
cgroup_init_early();

/*
* 禁用中断
* 早期阶段不处理中断
*/
local_irq_disable();
early_boot_irqs_disabled = true;

/*
* Boot CPU 初始化
*/
boot_cpu_init();

/*
* 页地址初始化
*/
page_address_init();

/*
* 打印内核横幅
*/
pr_notice("%s", linux_banner);
/* 输出: Linux version 6.12.38 ... */

/*
* 架构特定初始化
* 这是架构相关的第一个重要调用
*/
setup_arch(&command_line);

/*
* 静态键和静态调用初始化
* 这些是内核性能优化的基础
*/
jump_label_init();
static_call_init();

/*
* 早期安全初始化
*/
early_security_init();

/*
* Boot 配置
*/
setup_boot_config();

/*
* 处理命令行参数
*/
setup_command_line(command_line);
setup_nr_cpu_ids();

/* ... 更多初始化 ... */
}

5.3 setup_arch() - 架构特定初始化

5.3.1 x86_64 的 setup_arch()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/* arch/x86/kernel/setup.c */

void __init setup_arch(char **cmdline_p)
{
/*
* 保存命令行指针
*/
*cmdline_p = boot_command_line;

/*
* 初始化页地址映射
*/
page_address_init();

/*
* 初始化内核内存布局
*/
init_mem_mapping();

/*
* 解析 e820 内存映射
* 从 BIOS/UEFI 获取的内存信息
*/
parse_e820_table();

/*
* 初始化 memblock
* 早期内存分配器
*/
initmem_init();

/*
* 初始化内存资源
*/
e820__memory_setup();

/*
* ACPI/设备树初始化
*/
acpi_boot_table_init();
unflatten_device_tree();

/*
* APIC 初始化
* 中断控制器
*/
init_apic_mappings();

/*
* KASLR (内核地址空间随机化)
*/
if (kaslr_enabled()) {
randomize_base();
}

/*
* 分页初始化
*/
paging_init();

/*
* 早期微码加载
*/
load_microcode();

/*
* 更多架构特定初始化...
*/
}

5.3.2 ARM64 的 setup_arch()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* arch/arm64/kernel/setup.c */

void __init setup_arch(char **cmdline_p)
{
/*
* 保存命令行
*/
*cmdline_p = boot_command_line;

/*
* 初始化栈 canary
*/
boot_init_stack_canary();

/*
* 处理设备树
*/
setup_machine_fdt(__va(__fdt_pointer));

/*
* 初始化 memblock
*/
arm64_memblock_init();

/*
* 设置页表
*/
paging_init();

/*
* 初始化 CPU 特性
*/
cpuinfo_store_cpu();

/*
* 中断控制器初始化
*/
acpi_boot_init();
irqchip_init();

/*
* SMP 初始化
*/
smp_init_cpus();

/*
* 更多架构特定初始化...
*/
}

5.4 核心子系统初始化

5.4.1 完整的 start_kernel 序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
void start_kernel(void)
{
/* ... setup_arch 之前的初始化 ... */

/* ┌────────────────────────────────────────────────────┐ */
/* │ 中断和陷阱初始化 │ */
/* └────────────────────────────────────────────────────┘ */

/*
* 陷阱初始化
* 设置中断和异常向量表
*/
trap_init();

/*
* 内存管理核心初始化
*/
mm_core_init();

/*
* poking_init
* 用于修改只读内存的机制
*/
poking_init();

/*
* ftrace 初始化
* 函数跟踪基础设施
*/
ftrace_init();

/*
* 早期跟踪初始化
*/
early_trace_init();

/* ┌────────────────────────────────────────────────────┐ */
/* │ 调度器和并发控制 │ */
/* └────────────────────────────────────────────────────┘ */

/*
* 调度器初始化
* 在启用中断之前必须完成
*/
sched_init();

/*
* 检查中断是否意外启用
*/
if (WARN(!irqs_disabled(),
"Interrupts were enabled *very* early, fixing it\n"))
local_irq_disable();

/*
* 基数树和映射树初始化
* 用于数据结构管理
*/
radix_tree_init();
maple_tree_init();

/*
* Housekeeping 初始化
* 用于隔离管理任务
*/
housekeeping_init();

/*
* 工作队列早期初始化
*/
workqueue_init_early();

/*
* RCU (Read-Copy-Update) 初始化
*/
rcu_init();

/*
* 跟踪初始化
*/
trace_init();

/*
* initcall 调试支持
*/
if (initcall_debug)
initcall_debug_enable();

/*
* 上下文跟踪初始化
*/
context_tracking_init();

/* ┌────────────────────────────────────────────────────┐ */
/* │ 中断和定时器 │ */
/* └────────────────────────────────────────────────────┘ */

/*
* 早期中断初始化
*/
early_irq_init();

/*
* 中断控制器初始化
*/
init_IRQ();

/*
* tick 初始化
*/
tick_init();

/*
* RCU nohz 初始化
*/
rcu_init_nohz();

/*
* 定时器初始化
*/
init_timers();

/*
* SRCU 初始化
*/
srcu_init();

/*
* 高精度定时器初始化
*/
hrtimers_init();

/*
* 软中断初始化
*/
softirq_init();

/*
* 时间保持初始化
*/
timekeeping_init();

/*
* 架构特定时间初始化
*/
time_init();

/*
* 随机数生成器初始化 (需要时间)
*/
random_init();

/*
* KFENCE 初始化
*/
kfence_init();

/*
* 栈 canary 初始化
*/
boot_init_stack_canary();

/*
* 性能事件初始化
*/
perf_event_init();

/*
* 性能分析初始化
*/
profile_init();

/*
* 函数调用初始化
*/
call_function_init();

/*
* 启用中断
* 这是关键的转换点
*/
WARN(!irqs_disabled(), "Interrupts were enabled early\n");
early_boot_irqs_disabled = false;
local_irq_enable();

/*
* slab 分配器后期初始化
*/
kmem_cache_init_late();

/* ┌────────────────────────────────────────────────────┐ */
/* │ 控制台和设备 │ */
/* └────────────────────────────────────────────────────┘ */

/*
* 控制台初始化
* 注意: 这时中断已启用, 设备可能产生输出
*/
console_init();

/*
* 检查 panic 参数
*/
if (panic_later)
panic("Too many boot %s vars at `%s'", panic_later, panic_param);

/*
* 锁依赖检查器初始化
*/
lockdep_init();

/*
* 锁自我测试
*/
locking_selftest();

/* ┌────────────────────────────────────────────────────┐ */
/* │ 内存和进程管理 │ */
/* └────────────────────────────────────────────────────┘ */

#ifdef CONFIG_BLK_DEV_INITRD
/*
* initrd 检查
*/
if (initrd_start && !initrd_below_start_ok &&
page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
page_to_pfn(virt_to_page((void *)initrd_start)), min_low_pfn);
initrd_start = 0;
}
#endif

/*
* per-CPU 页面集初始化
*/
setup_per_cpu_pageset();

/*
* NUMA 策略初始化
*/
numa_policy_init();

/*
* ACPI 早期初始化
*/
acpi_early_init();

/*
* 后期时间初始化
*/
if (late_time_init)
late_time_init();

/*
* 调度时钟初始化
*/
sched_clock_init();

/*
* calibrate_delay
* 用于 BogoMIPS 计算
*/
calibrate_delay();

/*
* CPU 最终化
*/
arch_cpu_finalize_init();

/*
* PID IDR 初始化
*/
pid_idr_init();

/*
* 匿名 VMA 初始化
*/
anon_vma_init();

#ifdef CONFIG_X86
/*
* EFI 运行时服务
*/
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_enter_virtual_mode();
#endif

/*
* 线程栈缓存初始化
*/
thread_stack_cache_init();

/*
* 凭证初始化
*/
cred_init();

/*
* fork 初始化
*/
fork_init();

/*
* 进程缓存初始化
*/
proc_caches_init();

/*
* UTS 命名空间初始化
*/
uts_ns_init();

/*
* 密钥管理初始化
*/
key_init();

/*
* 安全框架初始化
*/
security_init();

/*
* 调试后期初始化
*/
dbg_late_init();

/*
* 网络命名空间初始化
*/
net_ns_init();

/*
* VFS 缓存初始化
*/
vfs_caches_init();

/*
* 页面缓存初始化
*/
pagecache_init();

/*
* 信号初始化
*/
signals_init();

/*
* seq_file 初始化
*/
seq_file_init();

/*
* proc 根目录初始化
*/
proc_root_init();

/*
* nsfs 初始化
*/
nsfs_init();

/*
* pidfs 初始化
*/
pidfs_init();

/*
* cpuset 初始化
*/
cpuset_init();

/*
* cgroup 初始化
*/
cgroup_init();

/*
* 任务统计初始化
*/
taskstats_init_early();

/*
* 延迟计费初始化
*/
delayacct_init();

/*
* ACPI 子系统初始化
*/
acpi_subsystem_init();

/*
* 架构后期 ACPI 初始化
*/
arch_post_acpi_subsys_init();

/*
* KCSAN 初始化
*/
kcsan_init();

/* ┌────────────────────────────────────────────────────┐ */
/* │ 最终初始化和用户空间启动 │ */
/* └────────────────────────────────────────────────────┘ */

/*
* 剩余初始化
* 不返回, 最终启动用户空间
*/
rest_init();

/* 不应该到达这里 */
}

5.5 rest_init() - 最终初始化

5.5.1 rest_init 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* init/main.c */

noinline __init void rest_init(void)
{
/*
* RCU 调度器启动
* 启用 RCU 响应式调度
*/
rcu_scheduler_starting();

/*
* 创建 kernel_init 线程
* 执行剩余的初始化并启动用户空间
*/
pid = kernel_thread(kernel_init, NULL, CLONE_FS);

/*
* 创建 kthreadd 线程
* 管理内核线程的创建
*/
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

/*
* 系统进入空闲状态
* CPU 0 现在可以被调度器使用
*/
cpu_startup_entry(CPUHP_ONLINE);
}

5.5.2 kernel_init 线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/* init/main.c */

static int __ref kernel_init(void *unused)
{
/*
* 设置完成标志
* 内核初始化完成
*/
system_state = SYSTEM_BOOTING;

/*
* 等待 kthreadd 完成
*/
wait_for_completion(&kthreadd_done);

/*
* 设置当前命名空间
*/
set_sysctl_init(NULL);

/*
* 执行基本的设置
* 包括 do_initcalls()
*/
do_basic_setup();

/*
* 打开 /dev/console
* 标准输入/输出/错误
*/
console_on_rootfs();

/*
* 尝试执行指定的 init 进程
*/
if (execute_command) {
run_init_process(execute_command);
panic("Requested init %s failed.\n", execute_command);
}

/*
* 尝试默认的 init 进程
*/
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;

/*
* 所有尝试都失败
*/
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/admin-guide/init.rst for guidance.");
}

5.6 initcall 机制

5.6.1 initcall 级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* init/main.c */

/* initcall 级别定义 */
static initcall_entry_t *initcall_levels[] __initdata = {
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
__initcall_end,
};

/* 对应的宏定义 */
#define pure_initcall(fn) __define_initcall("0", fn, 0)
#define core_initcall(fn) __define_initcall("1", fn, 1)
#define postcore_initcall(fn) __define_initcall("2", fn, 2)
#define arch_initcall(fn) __define_initcall("3", fn, 3)
#define subsys_initcall(fn) __define_initcall("4", fn, 4)
#define fs_initcall(fn) __define_initcall("5", fn, 5)
#define device_initcall(fn) __define_initcall("6", fn, 6)
#define late_initcall(fn) __define_initcall("7", fn, 7)

5.6.2 do_initcalls() 执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* init/main.c */

static void __init do_initcalls(void)
{
int level;

/*
* 按顺序执行所有 initcall
*/
for (level = 0; level < ARRAY_SIZE(initcall_levels); level++)
do_initcall_level(level);
}

/* 执行单个级别 */
static void __init do_initcall_level(int level)
{
initcall_entry_t *fn;

/*
* 遍历该级别的所有 initcall
*/
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
do_one_initcall(initcall_from_entry(fn));
}

/* 执行单个 initcall */
int __init_or_module do_one_initcall(initcall_t fn)
{
int count = preempt_count();
char msgbuf[64];
int ret;

/* 检查黑名单 */
if (initcall_blacklisted(fn))
return -EPERM;

/* 开始跟踪 */
do_trace_initcall_start(fn);

/* 执行 initcall */
ret = fn();

/* 结束跟踪 */
do_trace_initcall_finish(fn, ret);

/* 检查抢占和中断状态 */
msgbuf[0] = 0;
if (preempt_count() != count) {
sprintf(msgbuf, "preemption imbalance ");
preempt_count_set(count);
}
if (irqs_disabled()) {
strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
local_irq_enable();
}
WARN(msgbuf[0], "initcall %pS returned with %s\n", fn, msgbuf);

return ret;
}

5.6.3 常见 initcall 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* core_initcall 示例 */
static int __init example_core_init(void)
{
pr_info("Core initcall executed\n");
return 0;
}
core_initcall(example_core_init);

/* device_initcall 示例 */
static int __init example_device_init(void)
{
/* 初始化设备 */
platform_device_register(&example_device);
return 0;
}
device_initcall(example_device_init);

/* late_initcall 示例 */
static int __init example_late_init(void)
{
/* 后期初始化 */
return 0;
}
late_initcall(example_late_init);

5.6.4 initcall 调试

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 启用 initcall 调试 */

/* 方法1: 内核参数 */
initcall_debug

/* 方法2: 黑名单特定 initcall */
initcall_blacklist=example_initcall,another_initcall

/* 方法3: 检查 initcall 执行时间 */
/* 输出示例:
* calling example_initcall+0x0/0x0 @ 1
* initcall example_initcall+0x0/0x0 returned 0 after 123 usecs
*/

5.7 系统状态转换

5.7.1 系统状态枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* include/linux/kernel.h */

enum system_states {
SYSTEM_BOOTING,
SYSTEM_SCHEDULING,
SYSTEM_RUNNING,
SYSTEM_HALT,
SYSTEM_POWER_OFF,
SYSTEM_RESTART,
SYSTEM_SUSPEND,
};

/* 当前系统状态 */
enum system_states system_state __read_mostly;
EXPORT_SYMBOL(system_state);

5.7.2 状态转换图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─────────────────────────────────────────────────────────────┐
│ 系统状态转换 │
├─────────────────────────────────────────────────────────────┤
│ │
│ SYSTEM_BOOTING │
│ │ │
│ │ start_kernel() 开始 │
│ ↓ │
│ SYSTEM_SCHEDULING │
│ │ │
│ │ 调度器初始化完成 │
│ ↓ │
│ SYSTEM_RUNNING │
│ │ │
│ │ 系统完全运行 │
│ │ │
│ └─→ SYSTEM_HALT (halt) │
│ └─→ SYSTEM_POWER_OFF (poweroff) │
│ └─→ SYSTEM_RESTART (reboot) │
│ └─→ SYSTEM_SUSPEND (suspend) │
│ │
└─────────────────────────────────────────────────────────────┘

5.8 本章小结

start_kernel 流程回顾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
start_kernel()
├─ setup_arch() [架构特定]
├─ trap_init() [中断向量]
├─ mm_core_init() [内存管理]
├─ sched_init() [调度器]
├─ early_irq_init() [早期中断]
├─ init_IRQ() [中断控制器]
├─ console_init() [控制台]
├─ security_init() [安全框架]
└─ rest_init() [最终初始化]
├─ kernel_init()
│ └─ do_initcalls()
│ ├─ core_initcall
│ ├─ postcore_initcall
│ ├─ arch_initcall
│ ├─ subsys_initcall
│ ├─ fs_initcall
│ ├─ device_initcall
│ └─ late_initcall
└─ kthreadd()

时间线总结

时刻 事件
~1s startup_64/__primary_switch 完成
~1.2s start_kernel 开始
~1.5s setup_arch 完成
~2s sched_init 完成, 调度器启动
~2.5s console_init, 可以看到输出
~3s initcalls 开始执行
~3s-5s 设备驱动初始化
~5s 用户空间 init 启动
  • Title: Linux内核分析之基础知识-5
  • Author: 韩乔落
  • Created at : 2026-01-08 02:47:03
  • Updated at : 2026-01-19 13:40:38
  • Link: https://jelasin.github.io/2026/01/08/Linux内核分析之基础知识-5/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments