在上一篇文章中,我们反复的更换内核需要多次重启,而且如果内核版本与我们的软件时间差别太大很容易出现不兼容的问题。还有很多同学觉得make module这步过于耗时。那么如果能编译一个不需要module而且可以直接启动的内核岂不美哉。那么我们可以采用虚拟机启动的方式来调试我们的内核。


0x00 需求准备

linux源码,busybox源码


0x01 虚拟机?QEMU

此虚拟机非彼虚拟机,这个qemu虚拟机是一个开源的虚拟平台,一般用于各种系统仿真。安装教程这里不再赘述,可以根据自己的不同发行版版本来自行安装。一般也非常简单,不需要额外安装驱动什么的,只要把qemu软件包装上就可以了。


0x02 提取内核镜像

关于内核编译的过程可以参照上文,前面的步骤都一样,只是不再需要编译

sudo make modules
sudo make modules_install

这两步,直接编译出bzImage就可以使用了。同理,在替换完系统调用表之后也只需要执行到make bzImage就可以了。
编译完成bzImage之后,在任意目录新建一个文件夹 把 [linuxSource]/arch/x86/boot/bzImage 复制到这个文件夹,这样就提取了编译出来的内核镜像bzImage。


0x03 创建启动内存盘

从上面的步骤中可以发现,在编译过程中,我们不再编译modules。而在上文的Tips中也说到了,module最终会被打包成一个ramdisk启动盘文件被kernel加载,从而释放出其中的各种驱动和程序包。那么没有这个我们就需要自己建立一个加载进入内存的ramdisk文件系统。
执行命令

sudo dd if=/dev/zero of=./rootfs.img bs=400M count=1
mkfs.ext4 rootfs.img
sudo mkdir /mnt/tempMount
mount rootfs.img /mnt/tempMount

这四步我们分别创建了一个空的400M的数据文件,和给它安装上 extfs4文件系统。然后再mnt上创建了一个挂载点,并且把这个镜像临时挂载到这个挂载点上,这样就可以方便的对这个启动盘的内容进行操作了。
但是现在这个内存盘还只是个空壳,里面启动之后不会有任何东西。busybox就派上用场了。进入busybox的源码目录,执行命令

make menuconfig

并在出现的图形界面中选择BusyBox setting->Build options->Binary BusyBox as a static binary (no shared libs),将这一项勾选(目的是讲busybox生成为不需要动态链接执行的文件,作用之后会讲到)。然后执行

make -jn //jn含义一样
sudo make install CONFIG_PREFIX=/mnt/tempMount

这两步分别是编译了busybox的文件,和把编译好的文件放到刚才挂载的那个镜像中。现在我们的镜像盘中就有东西了,但是还不够,因为我们还需要将我们一个自己写的系统调用的程序放进去。编译上文的test.cpp生成test可执行文件,把它拷贝到 /mnt/tempMount/usr/bin/ 这个目录下。现在就万事俱备只欠东风了
把这个数据文件也放到我们刚才建立的那个文件夹中,用作这个系统的硬盘(内存盘)。


0x04 运行QUEM!

忙活了这么半天终于可以直接看到成果了,切到我们把原料都放好的那个新建文件夹,执行命令

qemu-system-x86_64 --kernel bzImage -hda rootfs.img  -append "root=/dev/sda rootfstype=ext4 init=/bin/ash"

这段代码的意思是 以bzImage为镜像启动 并加载一块硬盘 rootfs.img 为hd1(第一块硬盘在linux中命名为sda),然后指定启动参数 根目录为/dev/sda sda的文件系统是ext4 加载后启动的第一个程序是/bin/ash这个程序。然后敲下回车,就可以看到虚拟机跑起来了,成功的打开了和linux命令行一样的ash程序,在里面输入命令就可以查看我们的临时空间还有内核状态了~然后我们和上文一样输入命令

test
sudo dmesg|grep hello

就可以看到一样的。。。。。




一样个锤子,连test都跑不起来,test执行时提示 no such file or directory。但很奇怪的是,如果执行不了的话应该是 no command found啊,为什么提示的事没有找到文件呢


0x05 ????

百度百科:动态链接库文件,是一种不可执行的二进制程序文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows 提供的DLL文件中包含了允许基于 Windows 的程序在 Windows 环境下操作的许多函数和资源。一般被存放在电脑的”C:\Windows\System32″ 目录下。
Windows 中,DLL 多数情况下是带有 “.dll” 扩展名的文件,但也可能是 “.ocx”或其他扩展名;Linux系统中常常是 “.so” 的文件

我们知道,一般程序是由二进制序列组成,但是有的时候我们有大量的可以复用的程序部分,为了节省内存空间和硬盘空间,聪明的程序员们提出了一种动态加载的二进制文件,它们可以用于多个程序提供特定功能,可以看成特殊功能的部件。毫无疑问,我们编译的test文件在运行的时候也是要一些动态链接库支持的,所以我们要把它们也导进我们的文件系统中。执行命令

ldd test //查看test文件需要的动态链接库 得到结果
    linux-vdso.so.1 (0x00007fffd2f16000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f682fa9c000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007f682f789000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f682f572000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f682f1ce000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f682fe24000)
//其中第一个是包含在内核中的通用库不用管它,从第二个开始,把每一个都复制到我们的文件系统的对应目录
//以tempMount这个挂载点为新系统的根目录
sudo mount rootfs.img /mnt/tempMount
//比如第二个库 我们就需要
sudo mkdir /mnt/tempMount/usr/lib  //对应于 原系统的/usr/lib
sudo cp /usr/lib/libstdc++.so.6 /mnt/tempMount/usr/lib/
//其他文件也是

按照这样把所有动态库都复制进去之后 再次启动虚拟机,执行test和dmesg,我们就能看到想要的 hello了~

分类: 其他技术

发表评论

电子邮件地址不会被公开。