跟踪内核从start_kernel到init进程启动
2017-03-11 18:27
417 查看
黄二玉+原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
打开另一个shell窗口
跟踪内核从start_kernel到init进程启动
使用如下命令,设置断点
break start_kernel
break rest_init
break cpu_startup_entry
在命令行输入
start_kernel断点:
rest_init断点:
cpu_startup_entry断点:
最后窗口显示如下:
下面是rest_init函数
start_kernel函数是整个内核的入口,set_task_stack_end_magic(&init_task)设置第一个进程(pid=0),rest_init这是Linux内核初始化的尾声, kernel_thread(kernel_init, NULL, CLONE_FS)创建一个进程(pid=1)
cpu_idle_loop是一个无限循环的函数,pid=0的进程(idle进程)根本就不会结束,当没有别的任务,该进程就被调用。
所以pid=0的进程是从start_kernel开始被创建,该进程主要负责各个模块的初始化工作,并在rest_init中创建pid=1的进程,然后继续执行,直到进入 cpu_idle_loop循环函数,变为idle进程。
预备知识
使用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进程。
相关文章推荐
- Linux内核分析之三——使用gdb跟踪调试内核从start_kernel到init进程启动
- Linux内核分析-使用gdb跟踪调试内核从start_kernel到init进程启动
- 跟踪分析Linux内核的启动过程(start_kernel到init进程启动)
- 使用gdb跟踪调试内核从start_kernel到init进程启动
- MOOC-Linux内核lab3 调试内核从start_kernel到init进程启动
- (作业3)Linux内核的启动过程(从start_kernel到init进程启动)
- start_kernel到init进程启动的过程
- start_kernel到init进程启动的过程
- 内核启动kernel_init(init)进程分析
- linux启动流程(从start_kernel中的rest_init函数到init进程(1))
- kernel 启动过程之四,start_kernel中的rest_init函数到init进程
- 分析Linux内核启动过程:从start_kernel到init
- Linux系统启动分析-从start_kernel到init进程的启动
- 从start_kernel到init进程启动 《Linux内核分析》笔记
- 分析Linux内核启动过程:从start_kernel到init
- 内核启动阶段kernel_init(init)进程分析
- MOOC课程《Linux内核分析》——start_kernel();Idle进程与Init进程
- arm-linux内核start_kernel之前启动分析(1)-接过bootloader的衣钵
- arm linux 启动之二:start_kernel到创建1号进程
- arm linux 启动之二:start_kernel到创建1号进程