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

 一. 实验过程

1、打开shell,输入启动指令,内核启动完成后进入menu程序,支持三个命令help、version和quit。

2、然后使用gdb跟踪调试内核,输入命令qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 

3、按住Ctrl+ALt键打开一个新的Shell窗口,并输入以下代码。

  1. gdb
  2. (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
  3. (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
  4. (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程序。

 

总结:

浅入的学习了xLinux内核的启动过程。

学习了gdb的操作使用。

x86 CPU启动的第一个动作CS:EIP=FFFF:0000H(换算为物理地址为000FFFF0H,因为16位CPU有20根地址线),即BIOS程序的位置。BIOS例行程序检测完硬件并完成相应的初始化之后就会寻找可引导介质,找到后把引导程序加载到指定内存区域后,就把控制权交给了引导程序。引导程序BootLoader开始负责操作系统初始化,然后起动操作系统。启动操作系统时一般会指定kernel、initrd和root所在的分区和目录。内核启动过程包括start_kernel之前和之后,之前全部是做初始化的汇编指令,之后开始C代码的操作系统初始化,最后执行第一个用户态进程init。一般分两阶段启动,先是利用initrd的内存文件系统,然后切换到硬盘文件系统继续启动。