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

黄二玉+原创作品转载请注明出处 + 《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断点:
start_kernel
rest_init断点:
rest_init
cpu_startup_entry断点:
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进程。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值