在Windows下通过虚拟机搭建Linux内核的学习和调试环境

  其实,这边文章在我的linux的repo里面已经介绍了,此处着重进行归纳和整理。

本文重点

  • Windows下虚拟机的嵌套
  • 内核编译和ramfs镜像的制作
  • Qemu使用特定内核启动

一、Windows下面VMware虚拟机嵌套KVM虚拟机

  像我之前用Gentoo,然后搭建个KVM的虚拟机,编译启动内核是十分方便的。但是碍于现在在Windows环境工作的原因,使用Gentoo作为桌面系统,还是有些不方便的。
  此外还有的一个原因,是感觉自己过了那种折腾的年龄了。往昔那种优化美化Linux桌面,寻求各种方式替代Windows的应用软件,对我已经没有任何的吸引力了。(我已老矣)
  在Windows下,至少需要一个Host来交叉编译内核,然后再找个Host启动跟踪这个内核,在一台机器上面如果用虚拟机,势必涉及到虚拟机的嵌套(因为如果开两个虚拟机,我还不知道调试的虚拟机怎么指定内核来启动,除非你将新内核拷贝到测试机覆盖文件系统上的内核,显然很麻烦!!!)Qemu+KVM就是这帮搞Linux的维护开发的,看看Qemu的启动参数就能吓尿你,所以用这家伙学内核乃是正道。
  默认的VMware是不支持这种嵌套虚拟化的,需要修改虚拟机的配置文件。我用的VMware Workstation 9,测试添加这些内容可行

1
2
3
apic.xapic.enabled = "FALSE"    
vcpu.hotadd = "FALSE"
hypervisor.cpuid.v0 = "FALSE"

  然后在VMware里面安装你的Guest(将来也是Host)的系统吧!(我用的地沟油,贱兔太浪费时间和精力了)
  然后用qemu或者virt-manager再建立一个真正的Guest系统,我同样使用的Fedora。怎么用qemu或者virt-manager装系统,我不想说,你可以去参考archlinux或者gentoo的wiki。

二、产生内核和initrd文件

2.1 配置和编译内核

  内核我直接Fork的Linus的内核,所以是最upstream的。我想做代码的学习和注解工程有兴趣的可以联系我一块学习讨论。
  配置编译内核就是

1
2
make menuconfig
make

  两步曲,宇宙人都知道,不再细描。缺的第三步我要在下面说!

2.2 产生initrd文件

  如果你直接make install,内核会被装到你系统的/boot分区去,在内核的Makefile文件中写道

# INSTALL_PATH specifies where to place the updated kernel and system map
# images. Default is /boot, but you can set it to other values

# INSTALL_DTBS_PATH specifies a prefix for relocations required by build roots.
# Like INSTALL_MOD_PATH, it isn’t defined in the Makefile, but can be passed as
# an argument if needed. Otherwise it defaults to the kernel install path
就是说这两个变量可以指定你的安装目录,英语烂的自行机器翻译去吧。

1
2
3
4
5
6
7
8
9
➜  linux git:(master) mkdir ../INSTALL_PATH
➜ linux git:(master) make INSTALL_PATH=../INSTALL_PATH install
sh ./arch/x86/boot/install.sh 4.2.0-rc7+ arch/x86/boot/bzImage \
System.map "../INSTALL_PATH"
➜ linux git:(master) make INSTALL_MOD_PATH=../INSTALL_PATH modules_install
➜ linux git:(master) cd ../INSTALL_PATH
➜ INSTALL_PATH ls
config-4.2.0-rc7+ lib vmlinuz-4.2.0-rc7+
System.map-4.2.0-rc7+

  对于指定了安装目录,那么不用root权限也可以安装的。能不用root权限就不要用,以防对Host主机造成破坏。此外,在地沟油下面会出现

ln: failed to create symbolic link ‘/boot/System.map’: Permission denied
ln: failed to create symbolic link ‘/boot/vmlinuz’: Permission denied
ln: failed to create symbolic link ‘/boot/System.map’: Permission denied
  遇见这样的警告,请忽视之。
  对比/boot目录,我们发现少了initramfs文件,这个文件的作用不用说了,没有他多半系统起不来。在Gentoo中是genkernel工具可以自动生成的,在地沟油中,用dracut就可以生成(Gentoo中也可以安装使用dracut的)

1
➜  INSTALL_PATH sudo dracut -f -v -k './lib/modules/4.2.0-rc7+' initramfs.img 4.2.0-rc7+

  如果你对initramfs里面有哪些东东感兴趣,可以使用

1
lsinitrd initramfs.img

  这个命令查看的。

三、用制定的内核启动嵌套的虚拟机

  上面的准备工作准备好了,就可以用上面出炉的内核以及initrd启动系统了。
  这里啰嗦一句,可能人家对Qemu、KVM有点混乱,这么说吧,Qemu本身是一个天才所作的完整的虚拟机方案,可以虚拟很多种架构,而KVM是底层内核对虚拟化的支持,直接用Qemu也可以建虚拟机,只是速度龟慢,而Qemu+KVM用到内核虚拟化的支持,可以大大提高虚拟机的性能,这时候Qemu就是一个掌管虚拟机的工具了。
  qemu的启动参数很多,下面直接贴出命令出来了,相信都不难理解,这个吧虚拟机的串口输出导出成一个服务端,用网络的方式可以在Host另外一个终端接收
  启动分为两个类别

3.1 使用Xmanager启动图形界面

  安装Xmanager后,打开Xmanager - Passive,同时设置DISPLAY环境变量(IP地址就是VNET8的地址,0.0查看Xmanager系统托盘的显示结果,有时候可能是0.1或者其他的):

1
2
➜  INSTALL_PATH  export DISPLAY=192.168.200.1:0.0
➜ INSTALL_PATH qemu-system-x86_64 -enable-kvm -cpu host -smp 2,sockets=1 -m 512M -drive file=/home/user/Machines/Fedora.img,if=virtio,cache=writethrough -serial telnet:127.0.0.1:4444,server -kernel ~/GitHub/INSTALL_PATH/vmlinuz-4.2.0-rc7+ -initrd ~/GitHub/INSTALL_PATH/initramfs.img -append "root=/dev/vda1 init=/usr/lib/systemd/systemd console=uart8250,io,0x3f8 debug ignore_loglevel"

  然后打印出

1
QEMU waiting for connection on: disconnected:telnet:127.0.0.1:4444,server

  此时在另外一个终端执行

1
➜  INSTALL_PATH telnet 127.0.0.1 4444

3.2 Headless启动方法

  如果没有图形界面,就不需要Xmanager和DISPLAY了,直接在qemu的启动参数添加 –nographic参数就可以了。

四、运行效果图

系统启动界面
系统启动界面
系统登陆界面
系统登陆界面

本文完!