构建调试Linux内核网络代码的环境MenuOS系统
内核编译
下载linux内核源代码
命令
mkdir LinuxKernel #首先创建一个目录,作为本次实验的工作目录,名字随意
cd LinuxKernel #进入该工作目录
sudo wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz #下载linux-5.0.1的内核
sudo xz -d linux-5.0.1.tar.xz #解压后缀为xz的内核文件,并在解压完成之后删除原压缩文件
tar -xvf linux-5.0.1.tar #解压新生成的tar后缀的压缩文件
截图
在下载linux-5.0.1的内核这一步可能需要的时间较长,不挂梯子的话速度有些难顶。
安装内核编译工具
命令
sudo apt install aptitude #解决各种依赖问题,安装一次永久清爽
sudo apt install build-essential
sudo apt install flex
sudo apt install bison
sudo apt install libssl-dev
sudo apt install libelf-dev
sudo apt install libncurses-dev
注意事项
在Ubuntu中安装libssl-dev
的时候系统总是失败,其原因如下:
我想着:那么先将这个编译工具所需要依赖的软件全部安装应该就能行了吧?
结果,这些软件又有依赖关系!
而aptitude
就是用来治各种依赖问题的,再也不需要手动添加依赖包了。
之后就可愉快地安装所需的内核编译工具了。
配置编译内核
命令
cd linux-5.0.1 #进入之前解压好的内核目录
sudo make i386_defconfig #生成32位的配置文件
sudo make menuconfig #进入内核裁剪界面
界面配置选项
在执行命令sudo make menuconfig
之后出现以下界面。
按照以下顺序依次选择
:
-
选
Kernel hacking
-
选
Compile-time checks and compiler options
-
选
Compile the kernel with debug info
输入Y
-
保存并一路
Exit
退出界面
编译
sudo make #编译内核
然后,可以稍事休息一下。
等待大约半小时,编译过程结束。。。
升级当前系统内核
命令
sudo make modules_install #安装前通过系统快照备份系统
sudo make install
sudo update-grub
reboot
uname -a
这里只是展示执行命令,我自己是没有成功的,原因如下。
失败与恢复操作
前面两步我是执行成功的,但是在重启系统之后就出问题了。
在重启后,Ubuntu会卡在这个界面。
我前前后后等了大概1个多小时,等的我有些绝望,差点我就删系统了。
还好,在谷歌百度一番之后,终于找到了解决方法
:
在反复启动失败之后,Ubuntu会出现一个启动的高级选项
,选择这个高级选项后会发现它能够按照指定的内核版本来进行启动。
这时候,只要选择除linux-5.0.1
之外的选项就能够恢复了。
执行命令的失败可能与本人安装的系统、环境有关,诸君可大胆尝试去执行。
制作根文件系统
QEMU虚拟机加载内核
命令
sudo apt install qemu # 安装qemu命令
构造MenuOS
命令
cd /LinuxKernel #进入工作目录
mkdir rootfs #创建MenuOS根目录
sudo git clone https://github.com/mengning/menu.git #下载menu系统
cd menu
sudo apt-get install libc6-dev-i386 #在64位环境编译32位需要安装
sudo chmod 777 Makefile #将Makefile从只读修改为可读写
vim Makefile #修改Makefile中的内核版本
运行截图
GitHub的下载速度一直很神奇,挂不挂梯子速度都差不多,好在文件不大,等待一段时间就好了。
我们所使用的内核版本是linux-5.0.1
,因此在menu
的Makefile
文件中我们也要将其编译所依赖的内核修改过来。
值得一提的是:若是你编译所依赖的内核
位置与本人不一致,还需要修改其中的目录信息。
编译
命令
sudo make rootfs #初始化根目录
运行截图
测试MenuOS环境
将TCP网络通信程序的服务器端集成到MenuOS系统
命令
cd /LinuxKernel #进入工作目录
sudo git clone https://github.com/mengning/linuxnet.git #下载实验代码
cd linuxnet/lab2 #进入服务器目录
sudo make #编译前检查一下Makefile文件中的目录是否与自己的匹配
cd ../../menu/
sudo make rootfs #编译,将服务器端集成到系统中
注意事项
在实验二的代码编译之前,我们需要看一下其Makefile文件的内容:
可以看到按照Makefile
文件的内容,编译之后会将lab2
目录中的两个代码文件拷贝到menu
目录中,
但是前提是你的工作目录结构与其所指定的一致。
将TCP网络通信程序的客户端集成到MenuOS系统
命令
cd /LinuxKernel #进入工作目录
cd linuxnet/lab3 #进入客户端目录
sudo make #同样,在编译前检查一下Makefile,修改其内核版本
sudo make rootfs #编译,将客户端集成到系统中
注意事项
我们查看lab3
目录下的Makefile
文件,发现与之前menu
目录下的Makefile
有些类似。
是的,这里需要修改的也是编译所依赖的内核的版本。
运行截图
在我们将客户端与服务器端都集成到系统之后,qemu
虚拟机所显示的结果与之前构建MenuOS
的相同。
但是输入命令help
后会看到其中已经添加了客户端
以及服务器端
所对应的replyhi
和hello
命令。
测试一下这两个命令,可以得到客户端
与服务器端
交互的结果。
构建Linux内核的gdb调试环境
在qemu中启动gdb server
命令
sudo qemu -kernel ../linux-5.0.1/arch/x86/boot/bzImage -initrd ../rootfs.img -append nokaslr -s -S
运行截图
在新打开的qemu
虚拟机上,出现的是一个黑屏,此时的qemu
在等待gdb
的连接。
gdb调试
命令
#新建一个终端,在新终端执行以下命令
gdb #进入gdb命令行
file ../LinuxKernel/linux-5.0.1/vmlinux #在gdb界面中targe remote之前加载符号表
break start_kernel # 设置断点
target remote:1234 # 建立gdb和gdbserver之间的连接
c #continue,让qemu上的Linux继续运行
list #查看断点处的代码。
运行截图
在gdb
界面中targe remote
之前加载符号表,如果没有加载的话,后面则无法根据符号来设置断点
我们在start_kernel
处设置断点
其执行结果如下。
按c后让qemu
上的Linux
继续运行,可以看到之前一直黑屏的界面继续执行了。
使用list
命令,可以查看断点处的源代码,其结果如下图。