目录
实验三:跟踪分析 Linux 内核的启动过程
实验说明:
使用实验楼的虚拟机打开 shell
cd ~/LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
内核启动完成后进入 menu程序(《软件工程 C 编码实践篇》的课程项目),支持三个命令 help、version 和 quit,您也可以添加更多的命令,对选修过《软件工程 C 编码实践篇》的童鞋应该是 a piece of cake.
使用 gdb 跟踪调试内核
$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
# 关于-s和-S选项的说明:
# 1. -S
# -S freeze CPU at startup (use ’c’ to start execution)
# 2. -s
# -s shorthand for -gdb tcp::1234
# 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
另开一个 shell 窗口
# 打开 GDB 调试器
$ gdb
# 在 GDB 中输入以下命令:
# 在gdb界面中targe remote之前加载符号表
(gdb)file linux-3.18.6/vmlinux
# 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
(gdb)target remote:1234
# 断点的设置可以在target remote之前,也可以在之后
(gdb)break start_kernel
实验要求:
- 使用 gdb 跟踪调试内核从 start_kernel 到 init 进程启动
- 详细分析从 start_kernel 到 init 进程启动的过程并结合实验截图撰写一篇署名博客,并在博客文章中注明“真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux 内核分析》MOOC 课程 Linux内核分析 - 网易云课堂 ”,博客内容的具体要求如下:
- 题目自拟,内容围绕 Linux 内核的启动过程,即从 start_kernel 到 init 进程启动;
- 博客中需要使用实验截图
- 博客内容中需要仔细分析 start_kernel 函数的执行过程
- 总结部分需要阐明自己对“Linux 系统启动过程”的理解,尤其是 idle 进程、1 号进程是怎么来的。
请提交博客文章 URL 到网易云课堂 MOOC 平台 Linux 内核分析 MOOC 课程,编辑成一个链接可以直接点击打开(学堂在线上的学员注意提交博客 URL 到学堂在线上)
实验过程:
- 在实验楼中的shell中执行以下命令
可以看到上述命令启动的内核开始时属于stop状态
此时打开另一个shell窗口,再使用如下命令
可以看到QEMU继续运行了
接着我们在start_kernel处设置断点,下面使用continue命令
可以看到内核代码运行到start_kernel()函数处遭遇断点,暂停执行,接着再通过l命令查看start_kernel处上下的代码:
再在rest_init处设置一个断点,并使用continue命令
可以看到,内核再一次暂停,再使用l命令
实验总结:
start_kernel()相当于C语言中的main函数,它是一切的起点,在该函数被调用之前,内核代码主要是用汇编语言写的,用于完成该硬件系统的初始化工作,为c代码的运行设置环境。通过start_kernel()函数调用内部模块init_task()来创建init进程,接着init_task()(PID为0)在创建了init进程后,调用cpu_idle()演变成了idle进程,执行一次调度后,init进程运行。1号内核线程负责执行内核的部分初始化工作及进行系统配置,最后调用do_execvc加载init程序,演变成init进程(用户态1号进程),init进程是内核启动的第一个用户态进程。kthreadd(PID为2)进程由0号进程创建,始终运行在内核空间,负责所有内核线程的调度和管理。