LINUX内核分析第三周学习总结:构造一个简单的LINUX系统MENUOS
5234 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
构造一个简单的Linux系统
1. 运行MenuOS系统
-
在实验楼的虚拟机环境里,打击打开shell,使用下面的命令
cd LinuxKernel/ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img # -initrd:指明一个根文件系统
- 启动实验的Linux系统MenuOS,实际上就是一个在Linux内核的基础上,再运行一个简单菜单命令行程序。
-
在MenuOS>的提示符下输入help,看到其全部支持的命令:
help、version、quit
。
2. 使用gdb跟踪调试内核
-
使用带参数命令启动MenuOS,使得系统在刚启动时,暂停等待调试器跟踪执行。
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # -S 在CPU初始化之前,冻结CPU # -s 1234端口上创建一个tcp接口。若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
-
另开一个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 # 在start_kernel函数入口处设置断点 (gdb)c # 使得系统运行到start_kernel处停住 (gdb)list # 显示当前行所在位置上下的代码
附:常用调试参数
常用调试参数 | 用途 |
---|---|
r(run) | 开始运行程序 |
c(continue) | 继续运行一直到断点停止 |
b(break) | 设置程序断点 |
l(list) | 显示当前行后面的源程序 |
bt (backtrace) | 查看堆栈信息 |
info | 查看各类gdb信息以及环境信息,比如:info break可以查看断点信息 |
p(print) | 打印出变量值;如 p var,会把var变量的值输出 |
s(step) | 单步跟踪,会进入函数内部 |
n(next) | 单步跟踪,不进入函数 |
finish | 跳出函数调试,并打印返回时的信息 |
clear | 清除全部已定义的断点 |
q(quit) | 退出gdb |
3、按住Ctrl+ALt键打开一个新的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之前,也可以在之后
将break 放在start处输入C ,观察qemu
输入list可以查看断点附近的代码。
查看linux-3.18.6的内核代码。这里有很多个文件目录。
其中arch包括了所支持的多种CPU体系结构,这里我们只关心里面的x86文件夹就好了。
其他还有如drivers为驱动相关代码。fs为文件系统相关内核代码,ipc是进程相关代码,mm是存储管理代码,net是和网络相关的内核代码等等。、
init为初始化相关的模块,在init/main.c/start_kernel中之后开始C代码的操作系统初始化,最后执行第一个用户态进程init。。
在start_kernel函数中可以看到很多_init相关函数,涉及到操作系统启动相关的多种初始化操作。
这里的init_task为相当于0号进程的pcb。 还有sched_init();为进程调度相关初始化。trap_init();为中断相关的内核代码。等等。
这里看到start_kernel 最后一句 rest_init().
当操作系统为空闲时,就会执行这个idle程序。