您的位置:首页 > 运维架构 > Linux

跟踪分析Linux内核的启动过程

2016-03-11 17:25 786 查看
余星光 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

1、实验目的:

        跟踪分析一个简单的Linux内核启动过程,理解操作系统是怎么启动的。

2、预备知识:

gdb调试常用参数
r(run)   开始运行程序;
c(continue)    继续运行一直到断点停止
b(break)   设置程序断点
p(print)   打印变量值
s(step)   单步跟踪,进入函数内部
n(next)   单步跟踪,不进入函数
finish   跳出函数调试,并打印返回时的信息
u(until)   跳出循环体
q(quit)   退出gdb
l(list)   显示当前行后面的源程序
bt(backtrace)    查看堆栈信息
info   查看各类gdb信息以及环境信息
clear   清除全部已定义的断点
delete    删除指定的断点


3、实验过程

3.1 使用实验楼虚拟机打开shell,执行如下命令:

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

运行效果如下:



输入help命令,可以看到系统支持三个简单命令:help、version、quit

3.2 使用gdb跟踪调试

1) 另开一个shell窗口,进入LinuxKernel目录,输入如下命令

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s –S
效果如下



# 关于-s和-S选项的说明:

# -S freeze CPU at startup (use ’c’ tostart execution) 在系统启动的时候冻结CPU,使用c键继续执行后续操作

# -s shorthand for -gdb tcp::1234 打开远程调试端口,若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

2) 打开另外一个shell终端,执行以下命令

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之前,也可以在之后
(gdb)c


运行截图如下:



        系统执行到start_kernel()函数,输入list命令可以查看之后的代码;利用break设置断点,c继续执行,list查看函数代码可以方便调试Linux启动过程中用到的任何函数。



4、分析start_kernel()函数

        start_kernel()类似C程序中的main函数。在start_kernel()函数之前,内核的代码都是用汇编写的,主要工作是完成一些最基本的初始化与环境设置工作;在start_kernel()中Linux将完成整个系统的内核初始化,在start_kernel的最后,是调用rest_init函数,在rest_init函数中,内核将产生第一个真正的进程,即pid=1的1号进程,而在start_kernel函数中init_task是静态制造出来的,pid=0,我们可以在start_kernel函数的开始处,看到其被初始化的代码,它试图将从最早的汇编代码一直到start_kernel的执行都纳入到init_task进程上下文中,在其初始化工作完成后,就会成为系统的idle进程。事实上在更早前的sched_init函数中,通过init_idle(current,
smp_processor_id())函数的调用就已经把init_task初始化成了一个idle task,init_idle函数的第一个参数current就是&init_task,在init_idle中将会把init_task加入到cpu的运行队列中,这样当运行队列中没有别的就绪进程时,init_task(也就是idle task)将会被调用,它的核心是一个while(1)循环,在循环中它将会调用schedule函数以便在运行队列中有新进程加入时切换到该新进程上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: