我是靠谱客的博主 标致冷风,这篇文章主要介绍跟踪分析Linux内核的启动过程,现在分享给大家,希望可以做个参考。

陈良 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://www.xuetangx.com/courses/course-v1:ustcX+USTC001+_/about

1. 调试gdb

(1)运行qemu

(2)运行gdb并链接remote

(3)设置断点break start_kernel,break rest_init


2. 分析start_kernel

在断点处停止:


分析start_kernel

复制代码
1
asmlinkage __visible void __init start_kernel(void)
函数中最后一行调用

复制代码
1
rest_init();
进入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
393static noinline void __init_refok rest_init(void) 394{ 395 int pid; 396 397 rcu_scheduler_starting(); 398 /* 399 * We need to spawn init first so that it obtains pid 1, however 400 * the init task will end up wanting to create kthreads, which, if 401 * we schedule it before we create kthreadd, will OOPS. 402 */ 403 kernel_thread(kernel_init, NULL, CLONE_FS); //kernel_init启动1号进程 404 numa_default_policy(); 405 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); //kthreadd创建了其他的内核线程 406 rcu_read_lock(); 407 kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); 408 rcu_read_unlock(); 409 complete(&kthreadd_done); 410 411 /* 412 * The boot idle thread must execute schedule() 413 * at least once to get things moving: 414 */ 415 init_idle_bootup_task(current); 416 schedule_preempt_disabled(); 417 /* Call into cpu_idle with preempt disabled */ 418 cpu_startup_entry(CPUHP_ONLINE); //调用cpu_idle_loop 419}
查看cpu_startup_entry

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
256void cpu_startup_entry(enum cpuhp_state state) 257{ 258 /* 259 * This #ifdef needs to die, but it's too late in the cycle to 260 * make this generic (arm and sh have never invoked the canary 261 * init for the non boot cpus!). Will be fixed in 3.11 262 */ 263#ifdef CONFIG_X86 264 /* 265 * If we're the non-boot CPU, nothing set the stack canary up 266 * for us. The boot CPU already has it initialized but no harm 267 * in doing it again. This is a good place for updating it, as 268 * we wont ever return from this function (so the invalid 269 * canaries already on the stack wont ever trigger). 270 */ 271 boot_init_stack_canary(); 272#endif 273 arch_cpu_idle_prepare(); 274 cpu_idle_loop(); //此处调用零号进程 275}
进入cpu_idle_loop查看

复制代码
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
189static void cpu_idle_loop(void) 190{ 191 while (1) { 192 /* 193 * If the arch has a polling bit, we maintain an invariant: 194 * 195 * Our polling bit is clear if we're not scheduled (i.e. if 196 * rq->curr != rq->idle). This means that, if rq->idle has 197 * the polling bit set, then setting need_resched is 198 * guaranteed to cause the cpu to reschedule. 199 */ 200 201 __current_set_polling(); 202 tick_nohz_idle_enter(); 203 204 while (!need_resched()) { 205 check_pgt_cache(); 206 rmb(); 207 208 if (cpu_is_offline(smp_processor_id())) 209 arch_cpu_idle_dead(); 210 211 local_irq_disable(); 212 arch_cpu_idle_enter(); 213 214 223 if (cpu_idle_force_poll || tick_check_broadcast_expired()) 224 cpu_idle_poll(); 225 else 226 cpuidle_idle_call(); 227 228 arch_cpu_idle_exit(); 229 } 230 239 preempt_set_need_resched(); 240 tick_nohz_idle_exit(); 241 __current_clr_polling(); 242 249 smp_mb__after_atomic(); 250 251 sched_ttwu_pending(); 252 schedule_preempt_disabled(); 253 } 254}

在cpu_idle_loop中while(1)一直循环,作为零号进程等待新的进程的创建

3. 总结

Linux内核的启动过程就是:

start_kernel启动,调用rest_init函数,生成零号进程并一直循环执行;

零号进程中又通过kernel_init创建了一号进程,并通过kthread创建了其他的内核线程。

最后

以上就是标致冷风最近收集整理的关于跟踪分析Linux内核的启动过程的全部内容,更多相关跟踪分析Linux内核内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部