文章目录
1.阅读学习教材「庖丁解牛Linux 分析 」第4章
2.教材深入学习关注豆列「Linux内核及安全」。
3.学习蓝墨云班课中第四周视频「构造一个简单的Linux系统MenuOS?」,并完成实验楼上配套实验三。
一、实验楼配套实验三
跟踪分析 Linux 内核的启动过程。
1、使用实验楼的虚拟机打开 shell
输入以下代码,实现构造内核:
cd ~/LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
2、使用 gdb 跟踪调试内核
输入以下命令,得到冻结的内核。其中,-S是指得到冻结的内核,-s是指在1234这个端口上创建gdb server用于建立连接。如果不想使用1234端口,可以使用-gdb tcp:xxxx来取代-s选项。
cd ~/LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
# 关于-s和-S选项的说明:
# 1. -S
# -S freeze CPU at startup (use ’c’ to start execution)
# 2. -s
# -s shorthand for -gdb tcp::1234
# 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
3、另外打开一个shell窗口
根据以下代码的指引,重新打开一个shell窗口,重新进入~/LinuxKernel/路径后,进行GDB调试,建立GDB和gdbserver之间的连接。此后,设置断点start_kernel,并按c让qemu上的冻结的Linux内核继续运行。
# 打开 GDB 调试器
$ gdb
# 在 GDB 中输入以下命令:
# 在gdb界面中targe remote之前加载符号表
(gdb)file linux-3.18.6/vmlinux
# 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
(gdb)target remote:1234
# 断点的设置可以在target remote之前,也可以在之后
(gdb)break start_kernel
查看start_kernel附近的代码:
4、再多次设置断点并进行查看
根据实验,使用 gdb 跟踪调试内核从 start_kernel 到 init 进程启动,接下来再次设置断点,并在QEMU中进行查看:
设置rest_init、kernel_init断点。
5、详细分析以上过程
内核从 start_kernel 到 init 进程启动期间,主要由 init/main.c 下的 start_kernel 函数完成。start_kernel 函数完成了设置 init_task(0 号进程)栈底、初始化处理器 ID、初始化追踪对象、初始化内存分页、初始化中断向量表、初始化内存分配器、初始化进程调度器、系统时钟设置、vfs 初始化等操作,最后执行arch_call_rest_init() 调用 rest_init(),即进入1号进程init。除此之外,idle进程是一个特殊的内核线程,通常由内核启动时的start_kernel()函数初始化。其主要任务是在系统没有其他可运行进程时,保持CPU处于空闲状态,它是一个轻量级的内核线程,用于消耗CPU空闲时间,以防止CPU无用地闲置。
此外,特别需要注意的是,0号进程就是整个系统的第一个进程,它负责确保系统的正常初始化和终止。而1号进程就是init进程,是用户态的第一个进程。
start_kernel():
start_kernel()函数是Linux内核的主要入口点,它负责完成内核的初始化和启动过程。主要任务包括:
初始化内核的数据结构,如页表、中断向量表、进程管理等。设置处理器ID。初始化内存管理子系统,允许内核使用虚拟内存。初始化进程调度器。设置系统时钟。初始化文件系统。
最终,start_kernel()函数通过调用rest_init()函数,将控制权转交给用户空间的初始化进程(即init 1号进程)。
rest_init():
rest_init()函数是start_kernel()的最后一步。它的主要任务是启动用户态的初始化进程,即1号进程init进程。这个过程包括:创建init进程的内核描述符和数据结构。调用kernel_execve()函数,加载用户空间的init程序,这将切换内核的执行上下文到用户态。一旦init进程开始运行,它负责执行系统初始化、加载用户空间的系统服务、网络配置等。
二、Chatgpt帮助
三、小结
通过本次实验,我了解了Linux内核的启动过程,包括从内核的起始点(0号进程)到用户态的第一个进程init(1号进程)的演变。这使我们对Linux内核的初始化、硬件初始化、内存管理、中断处理以及用户态进程的启动有了更全面的认识更深入地理解了Linux内核。