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

Linux内核的启动过程

一、构造一个简单的Linux内核

首先,在实验楼环境中将Linux系统和一个简单的文件系统运行起来:

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

二、跟踪调试内核的启动过程

# -s:在1234端口上创建一个gdb-server
# -S:CPU初始化之前冻结起来
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 

在另一个shell窗口中进行调试:

#进入LinuxKernel/下
cd ~/LinuxKernel/
# 打开GDB调试器
gdb
# 在gdb界面中targe remote之前加载符号表
(gdb)file linux-3.18.6/vmlinux 
# 建立gdb和gdbserver之间的连接
(gdb)target remote:1234

start_kernel函数相当于c语言的main函数,是一切的起点。因此,首先在start_kernel函数处设置断点进行分析。

# 在start_kernel处设置断点
(gdb)break start_kernel 
# 输入c运行至断点处
(gdb)c

单步执行分析start_kernel函数。其中,init_task变量相当于第一个进程的PCB,在此处进行初始化:

trap_init()实现中断向量的初始化,mm_init()实现内存管理的初始化,sched_init()实现调度模块的初始化,等等。

运行至最后是rest_init(),能够实现后续的初始化工作,正式执行内核线程和其他服务进程。

执行完rest_init()后,内核成功启动:

对rest_init函数设置断点,进一步调试分析:

单步执行。其中,rest_init函数通过调用kernel_thread()创建1号内核线程:

运行至最后,内核成功启动:

三、总结与分析

Linux内核启动过程:首先在入口start_kernel()处对0号进程init_task进行初始化,0号进程创建了1号内核线程kernel_init()和2号内核线程kthreadd()后,调用cpu_idle()转变为idle进程。1号内核线程kernel_init()负责执行内核的部分初始化工作及系统配置,之后调用do_execve演变成用户态1号进程;2号内核线程kthreadd()始终运行在内核空间,负责所有内核线程的调度和管理。

posted @ 2020-10-30 16:37  20209327  阅读(144)  评论(0编辑  收藏  举报