2020-2021-1 20209306 《linux内核原理与分析》第四周作业
一、实验部分
实验目的
在自己的Ubuntu中来搭建实验所需要的环境,使用qemu虚拟机运行内核,并用gdb跟踪调试内核从start_kernel到init进程启动。
实验过程
1.下载源代码并进行编译
先建立一个LinuxKernel文件夹mkdir LinuxKernel
,然后依次进行如下操作:
cd LinuxKernel
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz
xz -d linux-3.18.6.tar.xz
tar -xvf linux-3.18.6.tar
cd linux-3.18.6
make i386_defcongig
make
运行时出现错误如图
书上给的方法是在出错文件夹中下载compoler-gcc6.h即可,经过资料查阅,出错原因是Ubuntu环境版本与gcc编译器版本不匹配,这里将compiler-gcc5.h复制重命名为compiler-gcc9.h后放入该文件夹中来解决。
2.制作根文件系统
在LinuxLernel目录下进行操作
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
在执行编译指令gcc -pthread -o init linktable.c menu.c test.c -m32 -static
时报错如图
经过请教同学后得知时gcc缺少32位的环境,使用命令apt-get install gcc-multilib
安装multilib后不再报错。
3.对内核进行跟踪调试
sudo apt-get install qemu
下载qemu虚拟机,进行课本中的配置。
make menconfig
时报错
把缺少的部分用sudo apt-get install libncurses5-dev
补上就解决了,成功后如图
这个界面是为了配置内核编译的选项按照课本中的操作选择编译时携带调试信息,为了后面使用gdb进行调试,然后进行make操作。
4.跟踪调试Linux内核的启动过程
这里使用gdb跟踪调试内核,加两个参数,一个属-s(在1234端口创建一个gdb-server,这样就可以在另一个窗口用gdb把带有符号表的内核镜像加载进来,然后连接gdbserver,设置断点跟踪内核。
第二个-S是将CPU初始化之前冻结起来。
用qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s
启动内核。
这里报错
请教同学后用sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu
建立软链接解决。
接下来打开另一个窗口启动gdb,把内核加载进来,建立连接。使用如下代码:
file linux-3.18.6/vmlinux
target remote:1234
接下来开始设置断点
输入break start_kernel
查看start_kernel函数
输入break rest_init
查看rest_init函数
二、学习总结
由实验很大程度地了解了linux内核,实验中start_kernel是一切的起点,在此函数被调用之前,内核代码主要使用汇编语言写的,用于完成硬件系统初始化的工作。int_task在创建init进程后,调用cpu_idle演变成了idle进程,执行一次调度后,init进程运行。1号内核线程负责执行内核部分初始化工作及进行系统配置,最后调用do_execve加载init程序,演变为init进程,init进程是内核启动的第一个用户态进程。kthreadd进程由0号进程创建,始终运行在内核空间,负责所有内核线程的调度和管理。