-
安装开发工具
sudo apt install build-essential sudo apt install qemu # install QEMU sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev #编译内核所需的依赖---一些基础库
-
下载内核源码
sudo apt install axel axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz #下载源码压缩包 xz -d linux-5.4.34.tar.xz tar -xvf linux-5.4.34.tar #解压源码 cd linux-5.4.34
-
配置内核选项
make defconfig # Default configuration is based on 'x86_64_defconfig' make menuconfig # 打开debug相关选项 Kernel hacking ---> Compile-time checks and compiler options ---> [*] Compile the kernel with debug info [*] Provide GDB scripts for kernel debugging [*] Kernel debugging # 关闭KASLR,否则会导致打断点失败 Processor type and features ----> [] Randomize the address of the kernel image (KASLR)
-
编译和运行内核
make -j$(nproc) # nproc gives the number of CPU cores/threads available # 测试一下内核能不能正常加载运行,因为没有文件系统最终会kernel panic qemu-system-x86_64 -kernel arch/x86/boot/bzImage
-
制作内存根文件系统
首先从https://www.busybox.net下载 busybox源代码解压,解压完成后,跟内核一样先配置编译,并安装。 axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2 tar -jxvf busybox-1.31.1.tar.bz2 cd busybox-1.31.1 make menuconfig 记得要编译成静态链接,不用动态链接库。 Settings ---> [*] Build static binary (no shared libs) 然后编译安装,默认会安装到源码目录下的 _install 目录中。 make -j$(nproc) && make install
然后制作内存根文件系统镜像,大致过程如下: mkdir rootfs cd rootfs cp ../busybox-1.31.1/_install/* ./ -rf mkdir dev proc sys home sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/ 准备init脚本文件放在根文件系统跟目录下(rootfs/init),添加如下内容到init文件。 #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys echo "Wellcome MengningOS!" echo "--------------------" cd home /bin/sh 给init脚本添加可执行权限 chmod +x init 打包成内存根文件系统镜像 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz 测试挂载根文件系统,看内核启动完成后是否执行init脚本 qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz //本文由于将rootfs放在了linux文件夹下,命令如下: //qemu-system-x86_64 -kernel ./arch/x86/boot/bzImage -initrd rootfs.cpio.gz
图片结果显示
-
配置VScode
1、在命令行输入python ./scripts/gen_compile_commands.py 2、新建.vscode文件夹,将提供的配置文件放入文件夹内
-
跟踪分析
执行 qemu-system-x86_64 -kernel ./arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s 设置断点start_kernel,在vscode中按F5进行调试
可以看出,vscode停在了start_kernel处。
点击单点跳过,这里我们看到了0号进程init_task被设置整个系统的第一个进程(0进程是手工创建的,其他进程都是0号进程创建的)在内核引导时,init_task会被创建并启动,它是所有其他进程的起点。
继续跳过,start_kernel会继续执行一些初始化操作,包括初始化各种重要的数据结构、驱动程序、中断处理程序等。在这个阶段,内核会建立好一些必要的核心数据结构,如物理内存管理器、虚拟内存管理器,以及进程调度器等。
最后来到start_kernel的结尾arch_call_reset_init(),这个点开这个函数的定义是执行了reset_init()函数,因此我们再设置一个函数断点"reset_init",继续点击单点跳过发现就进入了reset_init函数内部。这个函数是由0号进程执行的。继续执行,这时候遇到了kernel_init,即1号进程,它是所有用户进程的祖先,由kernel_thread函数创建,kernel_thread函数创建一个新的内核线程(实际linux不支持线程所以是一个内核进程),该线程的入口地址是kernel_init()函数。
设置kernel_thread,继续执行,进入kernel_thread函数的定义。
发现kernel_thread函数是通过_do_fork函数来创建进程的。设置_do_fork断点,进入_do_fork函数定义。
_do_fork函数主要完成了调用copy_process()复制父进程、调用wake_up_new_task将子进程加入就绪队列等待调度执行等。
另一个进程则由kthreadd创建。 一共涉及到3个内核进程/线程。操作系统用数字来表示/记录一个进程/线程,此数字就被称为这个进程的进程号。这个号码是从0开始分配的。进程0:也就是那个死循环,也叫idle进程(空闲进程)。进程1:也就是kernel_init函数,这个进程被称为init进程。进程2:也就是kthreadd函数,这个进程是linux内核的守护进程。这个进程是用来保证linux内核自己本身能正常工作的。
基于VSCode的Linux内核调试环境搭建以及start_kernel跟踪分析
于 2023-03-23 21:06:50 首次发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)