3_GDB跟踪Linux内核启动过程

版权声明:陈诚
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

==================================================================

这周的实验是通过gdb工具,跟踪到linux内核代码中,分析启动过程。

进入实验楼环境后,打开终端如入命令运行后结果如下图:

cd LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img



输入help命令查看支持的3条命令如下图:



接下来输入如下命令运行后结果如下图:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 
# 关于-s和-S选项的说明: 	-S freeze CPU at startup (use ’c’ to start execution) 
			-s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
3_GDB跟踪Linux内核启动过程_第1张图片

接下来另开一个窗口gdb,输入如下代码运行后如下图:

gdb
(gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
(gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
(gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后


接下来敲入continue命令让系统继续运行,这是linux就开始初始化启动啦,并且会断在start_kernel函数处,此时我们用list命令就可以看到start_kernel函数前后的代码,如下图:

3_GDB跟踪Linux内核启动过程_第2张图片3_GDB跟踪Linux内核启动过程_第3张图片


还可以继续设置一个断点break rest_init,然后continue运行,如下图:



现在我们开始简单分析下start_kernel:
首先找到内核启动起点start_kernel(),它在内核代码文件夹init目录下的main.c文件中。可以在start_kernel()函数体中找到一个全局变量&init_task,它相当于在分析mykernel案例时候的0号进程创建的PCB,0号进程即最终的idle进程。所有模块的初始化都是通过start_kernel()函数调用进程初始化进行工作的。
在start_kernel()函数中还进行了很多函数的初始化工作,如:

    trap_init()用来中断的,初始化中断向量
    mm_init()内存管理模块初始化
    sched_init()调度模块初始化
    rest_init()中的run_init_process,init_process是linux系统中的1号进程,是第一个用户态进程,默认是根目录下的程序,如果根目录下没有,还会去找sbin/init,bin/init,sd/init其他路径下的程序来作为1号进程。
    kthreadd内核线程来管理系统资源
然后系统进入cpu_startup_entry(cpuhp_online) // call into cpu_idle with preempt disabled
当系统没有进程需要执行时就调度到idle进程
总结:rest_init()就是start_kernel从进程内核一启动的时候就一直会存在,就是0号进程
0号进程创建了1号进程以及其他的一些服务的内核线程,这样整个系统就启动起来了

你可能感兴趣的:(3_GDB跟踪Linux内核启动过程)