跟踪分析Linux内核的启动过程
2016-03-11 17:25
786 查看
余星光 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
1、实验目的:
跟踪分析一个简单的Linux内核启动过程,理解操作系统是怎么启动的。
2、预备知识:
3、实验过程
3.1 使用实验楼虚拟机打开shell,执行如下命令:
运行效果如下:
输入help命令,可以看到系统支持三个简单命令:help、version、quit
3.2 使用gdb跟踪调试
1) 另开一个shell窗口,进入LinuxKernel目录,输入如下命令
# 关于-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终端,执行以下命令
运行截图如下:
系统执行到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函数以便在运行队列中有新进程加入时切换到该新进程上。
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函数以便在运行队列中有新进程加入时切换到该新进程上。
相关文章推荐
- linux golang的安装
- linux下导入、导出mysql数据库命令
- 【Linux】一张图让你读懂Linux内核运行原理
- Linux-dd命令详解
- Configure PPPoE on CentOS7
- CentOS下Git服务器搭建
- 19幅图展现CentOS安装全过程
- 一张图让你读懂Linux内核运行原理
- Linux内核分析之三——使用gdb跟踪调试内核从start_kernel到init进程启动
- centos7下快速安装mysql
- linux c语言 select函数用法
- LINUX COMMAND NOTE
- Linux tail命令
- centos内网服务器搭建
- Linux端口详解
- Linux命令行下vim指令笔记
- Ubuntu linux系统下 su:出现: authentication failure的解决办法
- Linux下找不到so文件的解决办法
- phper的linux学习 -Lnmp搭建和svn的配置
- Linux防御小规模的DDoS攻击