2021-2022-1 20212813《Linux内核原理与分析》第四周作业

一、实验过程

1、内核直接启动

打开实验楼虚拟机环境,使用以下命令启动内核,结果如图所示。

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

图1.1

2、gdb 跟踪调试内核

使用以下命令启动调试内核,结果如下图所示,内核运行被冻结。

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
#-S  开始处冻结CPU,方便调试
#-s  使用tcp端口1234来进行通讯,将进程信息传过去(在后面的调试中会用到)。若不想使用1234端口,可以使用-gdb tcp:xxxx来取代-s选项

在这里插入图片描述在另一个shell中启动gdb,把内核加载进来,建立连接,并在内核开始函数start_kernel处设置断点,之后按下c继续执行程序,结果如下图所示:

# 在gdb界面中targe remote之前加载符号表
file linux-3.18.6/vmlinux
# 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
target remote:1234
# 断点的设置可以在target remote之前,也可以在之后
break start_kernel

在这里插入图片描述学会跟踪调试内核后,对start_kernel中的其他诸多函数设置了端点并进行调试分析,过程如图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、实验分析

通过对内核启动过程的调试,有以下几点分析:

1.start_kernel()

对于这个简单的Linux内核来说,start_kernel() 相当于是C中的main函数,是内核运行的起点,在此函数被调用之前内核代码是用汇编语言写的,完成系统的初始化工作,为c代码的运行设置环境。

2.init_task()

start_kernel() 函数几乎涉及到了内核的所有模块,如:trap_init()(中断向量的初始化)、mm_init()(内存管理的初始化)sched_init()(调度模块的初始化)等,首先是510行的init_task():

struct task_struct init_task = INIT_TASK(init_task);

可以看出 init_task(0号进程)是 task_struct 类型,是进程描述符,使用宏INIT_TASK对其进行初始化。接下来就是对各种模块的初始化,包括像trap_init、buffer_init、key_init等

3.rest_init()

通过rest_init()新建kernel_init、kthreadd内核线程:
在这里插入图片描述

kernel_thread()是 fork 出了一个新进程来执行kernel_init 函数,而 init_task 是使用宏进行初始化的。也就是说0进程不是系统通过 kernel_thread 的方式(也就是 fork)创建的(init_task 是唯一一个没有通过 fork()产生的进程)。
405行代码 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);调用 kernel_thread()执行 kthreadd函数,创建 PID=2的内核线程

三、实验总结

本周学习了对Linux内核函数跟踪调试,主要调试分析了start_kernel函数的运行过程,对于start_kernel函数中调用的一些起主要作用的函数(例如,trap_init、mm_init、rest_init等)有了初步的认识与了解。因为涉及的函数很多,实践过程中遇到更多的问题是不理解函数的具体作用,对于各初始进程创建过程的理解比较吃力,需要下更大的功夫查阅资料和分析代码。

微信扫码订阅
UP更新不错过~
关注
  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值