您的位置:首页 > 其它

跟踪内核从start_kernel到init进程启动

2017-03-11 18:27 417 查看
黄二玉+原创作品转载请注明出处 + 《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进程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: