实验相关:
尝试在自己的Ubuntu中来搭建实验所需要的环境。
1.下载内核源码
首先是下载内核源码(Linux-3.18.6)解压并编译,代码过程如下:
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
在编译过程中遇到书中提到的相似的错误,提示不存在compiler-gcc9.h这一文件,查阅相关资料,是Ubuntu环境版本与gcc编译器版本不匹配的原因,进入到include/linux环境下,发现其中最高的版本为compiler-gcc5.h,解决这个问题的方法有两种,一是在网络上下载compiler-gcc9.h放入相应文件夹中,二是将compiler-gcc5.h复制重命名为compiler-gcc9.h后放入该文件夹中。实践中采用方法二解决该问题,成功编译。
2.制作根文件系统
代码如下:
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.启动不带调试信息的Linux内核和MennuOS
自己环境中没有安装qemu,使用
sudo apt-get install qemu
安装qemu后,依然提示无法找到qemu,返回usr/bin目录中查找,发现只存在qemu-system-i386
通过Google后找到解决方法,可以建立一条软链接:
sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu
问题解决。
输入
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
启动成功
接下来是对内核进行跟踪调试,重新配置编译Linux内核,代码如下:
make menuconfig
make
重新配置编译Linux内核
4.跟踪调试Linux内核的启动过程(使用gdb跟踪)
(1)启动内核:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s
注:
- -s:在1234端口上创建了一个gdb-server,可用于之后设置断点跟踪内核;
- -S:使CPU初始化之前冻结起来。
(2)启动gdb输入如下指令加载内核,建立连接
file linux-3.18.6/vmlinux //在gdb界面中target remote之前加载符号表
target remote:1234 //用1234这个端口进行连接
(3)gdb中输入如下指令在start_kernel处设置断点
break start_kernel //可在target remote之前,也可在之后
查看star_kernel函数:
(4)gdb中输入如下指令在rest_init()处设置断点
break rest_init
查看rest_init()函数:
(5)分析
正如其名,strat_kernel是一切的起点,用于完成硬件系统的初始化工作,为C代码的运行设置环境。其中,比较重要的init_task是手工创建的PCB,是进程描述符,0号进程,即最终的idle进程。 通过rest_init()新建kernel_init和kthreadd内核线程。init_task()通过调用cpu_idle()转为idle进程,运行在内核空间;init_task()创建的kernel_init()(1号内核线程)通过调用do_execve可转为init用 户态1号进程,这是内核启动的第一个用户态进程;init_task()创建的kthreadd()(2号内核线程)始终运行在内核,负责所有内核线程的调度和管理。进程创建过程图如下图所示:
5.尚未解决的问题(目前已解决)
在自己的Ubuntu环境中使用gdb中会出现以下错误:

查阅资料说是编译时没有正确设置-g选项,这个-g选项不能直接放在编译命令中,要在makefile的开头定义CFLAGS 变量:CFLAGS = -g ,这样list命令才能列出源代码。时间原因我在实验楼环境下完成了这部分的实验,这几天忙完后再来看这个错误怎么解决。
6.后续补充
尝试在
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
中加入-g显示编译信息后成功通过,问题解决,猜测问题出在重新配置编译Linux内核中。重新检查后发现不知道什么原因导致compile the kernel with debug info未被选上,导致无法显示编译信息,再次选上后问题解决。