Linux内核_实验三:跟踪分析Linux内核的启动过程

郑斌    《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

该文章为课程的第三个实验记录及分析。

 

实验指导:

1.使用实验楼的虚拟机打开shell

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

内核启动完成后进入menu程序,支持三个命令help、version和quit,您也可以添加更多的命令.

2.使用gdb跟踪调试内核

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选项 

另开一个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之前,也可以在之后

 

实验环境:在实验楼中进行。

 

实验步骤:

打开shell,进入到LinuxKernel目录,通过qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img命令

运行对应的内核程序。

这里的  -initrd  rootfs.img的作用是指明根文件系统。  

 

可以看到menu程序已经启动。在这里支持help、version、quit共3个命令。分别为查看帮助,查看版本,和退出功能。

 

下面通过gdb调试来跟踪分心Linux内核的启动过程。

通过命令qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 。

参数-S的作用是在开始的时候,CPU初始化之前冻结CPU

参数-s 的作用是创建gdbserver,对应 tcp的1234号端口。若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项。

 

file linux-3.18.6/vmlinux     这是一个带debug信息的内核。该命令加载符号集

target remote:1234       建立gdbgdbserver之间的连接。

 

然后通过break设置断点,按c然程序继续执行到断点。按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的内存文件系统,然后切换到硬盘文件系统继续启动。

 

参考资料:课程学习文档视频以及互联网资料。

转载于:https://www.cnblogs.com/terrry/articles/4354695.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值