概述
黄二玉+原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
预备知识
使用gdb跟踪
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
打开另一个shell窗口
gdb
(gdb) file linux-3.18.6/vmlinux
(gdb) target remote:1234
(gdb) break start_kernel //设置断点
跟踪内核从start_kernel到init进程启动
使用如下命令,设置断点
- break start_kernel
- break rest_init
- break cpu_startup_entry
在命令行输入c
来继续运行程序,list
显示断点上下文。
start_kernel断点:
rest_init断点:
cpu_startup_entry断点:
最后窗口显示如下:
分析start_kernel函数的执行过程
下面是init/main.c中的start_kernel 函数
500 asmlinkage __visible void __init start_kernel(void)
501 {
502 char *command_line;
503 char *after_dashes;
504
505 /*
506 * Need to run as early as possible, to initialize the
507 * lockdep hash:
508 */
509 lockdep_init();
510 set_task_stack_end_magic(&init_task);
511 smp_setup_processor_id();
512 debug_objects_early_init();
.............
678
679 /* Do the rest non-__init'ed, we're now alive */
680 rest_init();
681 }
下面是rest_init函数
393 static 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);/*创建pid=1的进程*/
404 numa_default_policy();
405 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
........
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);/*注意这条语句,pid=0的进程变为了idle进程*/
419 }
start_kernel函数是整个内核的入口,set_task_stack_end_magic(&init_task)设置第一个进程(pid=0),rest_init这是Linux内核初始化的尾声, kernel_thread(kernel_init, NULL, CLONE_FS)创建一个进程(pid=1)
189 static void cpu_idle_loop(void)
190 {
191 while (1) {
192
............
253 }
254 }
255
256 void 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 */
...........
273 arch_cpu_idle_prepare();
274 cpu_idle_loop();
275 }
276
cpu_idle_loop是一个无限循环的函数,pid=0的进程(idle进程)根本就不会结束,当没有别的任务,该进程就被调用。
所以pid=0的进程是从start_kernel开始被创建,该进程主要负责各个模块的初始化工作,并在rest_init中创建pid=1的进程,然后继续执行,直到进入 cpu_idle_loop循环函数,变为idle进程。
最后
以上就是无语草丛为你收集整理的跟踪内核从start_kernel到init进程启动的全部内容,希望文章能够帮你解决跟踪内核从start_kernel到init进程启动所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复