进入 Linux 的世界以后,曾经也想过用虚拟机,比如 bochs 是我第一个接触的虚拟机,但是终究没有尝试多用用,随着对把玩各个 Linux distribution 的热情的消退,我开始集中在 fedora 后来迁移到 debian 上了,虚拟机似乎离我越来越远。直到 coLinux 的第二次接触重新点燃了我对虚拟机的热情。因此,准备在这里开始关于虚拟机的系列文章。而第一个也就是我最近才开始使用的 QEMU,偶然的机会让我能从 U 盘上 boot 偶的 Linux :-p
先看看 QEMU 的介绍,
QEMU is a fast processor emulator: currently the package supports我们需要先了解虚拟机究竟有些什么划分,才能理解 QEMU 究竟是什么。
arm, powerpc, sparc and x86 emulation. By using dynamic translation
it achieves reasonable speed while being easy to port on new host
CPUs. QEMU has two operating modes:
.
* User mode emulation: QEMU can launch Linux processes compiled for
one CPU on another CPU.
* Full system emulation: QEMU emulates a full system, including a
processor and various peripherals. It enables easier testing and
debugging of system code. It can also be used to provide virtual
hosting of several virtual PC on a single server.
.
As QEMU requires no host kernel patches to run, it is very safe and
easy to use.
对于虚拟技术(virtualization)有多种划分,请参考这篇文章。我们使用的 QEMU 属于 hardware simulation,亦即使用软件模拟硬件,因此效率低下不足为奇。但是注意前面的介绍,QEMU 支持多种体系结构,这使得我们甚至可以利用它测试其他平台,如 ARM 下的程序。这里顺便把其他的几个类型简单的比较一下,如 full virtualization,要求 client OS 是支持底层硬件的,似乎 VMWare (某个版本)属于这一类,虚拟软件本身担负起 mediator,避免 client OS 进入较本身更高的 ring。因此,该方式应该比前者快,速度损失在于 mediation。paravirtualization 这个词我第一次在 Xen 的主页上看到的,它需要通过修改 client OS 的 kernel 避免虚拟机本身 mediation,这样可以进一步提高虚拟机的效率。问题是很多 proprietary OS 是不可能修改其 kernel 的。还有一种是 operating system-level virtualization,这时虚拟机本身作为 OS 存在,而 client OS 作为应用程序。
好了,我们来看看 QEMU 里面都有些什么,
$ dpkg -L qemu可见,QEMU 对每个支持的体系结构提供了一个命令,另外 /etc 下面的脚本似乎是用来打开虚拟机和主机之间网络的,而/usr/share/qemu 里面是一些 BIOS。另外那个 /usr/sbin 里面的程序是用来制作一个不可以 boot 的 debian 的 / 的 disk file,这个东西应该可以在 coLinux 里面用用。
...
/usr/bin/qemu-img
/usr/bin/qemu-i386
/usr/bin/qemu-arm
/usr/bin/qemu-armeb
/usr/bin/qemu-sparc
/usr/bin/qemu-sparc64
/usr/bin/qemu-sparc32plus
/usr/bin/qemu-mips
/usr/bin/qemu-mipsel
/usr/bin/qemu-m68k
/usr/bin/qemu-alpha
/usr/bin/qemu-sh4
/usr/bin/qemu-sh4eb
/usr/bin/qemu-ppc
/usr/bin/qemu-ppc64
/usr/bin/qemu-ppc64abi32
/usr/bin/qemu-x86_64
/usr/bin/qemu-cris
/usr/bin/qemu
/usr/bin/qemu-system-sparc
/usr/bin/qemu-system-x86_64
/usr/bin/qemu-system-mips
/usr/bin/qemu-system-mipsel
/usr/bin/qemu-system-mips64
/usr/bin/qemu-system-mips64el
/usr/bin/qemu-system-arm
/usr/bin/qemu-system-ppc
/usr/bin/qemu-system-ppcemb
/usr/bin/qemu-system-ppc64
/usr/bin/qemu-system-m68k
/usr/bin/qemu-system-sh4
/usr/bin/qemu-system-sh4eb
/usr/bin/qemu-system-cris
/usr/sbin
/usr/sbin/qemu-make-debian-root
...
/etc
/etc/qemu-ifup
...
/usr/share/qemu/openbios-sparc64
/usr/share/qemu/openbios-sparc32
/usr/share/qemu/ppc_rom.bin
/usr/share/qemu/proll.elf
/usr/share/qemu/vgabios-cirrus.bin
/usr/share/qemu/vgabios.bin
/usr/share/qemu/bios.bin
下面讨论一下一些基本过程:既然 QEMU 是虚拟硬件完成的,那么我们相当于有一个裸机,我们需要给它安装操作系统,配置网络等等。那么它会提供我们哪些外设呢?
- i440FX host PCI bridge and PIIX3 PCI to ISA bridge因此,我们应该可以利用网络、光驱、硬盘、软盘甚至是 U 盘来启动我们的虚拟机。这在 qemu 的命令行参数里面可以找到,如 -fda 和 -fdb 就是软盘(或者软盘设备,似乎 QEMU 直接用 raw 的,硬盘也是 @@),-hda(bcd) 是硬盘,-cdrom 是光盘。这些设备都是可以用更加复杂的 -drive 产生,里面 if 那个 type 好像是有个 pflash,后面看看是否能用 -,-b。如果不是真需要将更新写入,可用 -snapshot。
- Cirrus CLGD 5446 PCI VGA card or dummy VGA card with Bochs VESA extensions (hardware level, including all non standard modes).
- PS/2 mouse and keyboard
- 2 PCI IDE interfaces with hard disk and CD-ROM support
- Floppy disk
- PCI/ISA PCI network adapters
- Serial ports
- Creative SoundBlaster 16 sound card
- ENSONIQ AudioPCI ES1370 sound card
- Adlib(OPL2) - Yamaha YM3812 compatible chip
- PCI UHCI USB controller and a virtual USB hub.
然后我们需要确定 boot 的设备,这是可以用 -boot 加上 a(软盘)、c(硬盘)、d(光驱)、n(网络)。内存用 -m n 指定 n Mb 的内存。-smp 可以指定多个 CPU 用于虚拟机。-soundhw 指定声卡类型。-localtime 指定使用当地时间,默认的是 UTC。-k 设定键盘 layout。-usb 和 -usbdevice 将把 USB 设备映射到 VM 上。-net 配置网络,可选 vlan、TAP 等连接方式。后面会详细介绍网络。网络启动需要设置 -tftp 和 -bootp,这和配置 Linux 网络启动的方式一致。-vnc 可以把视频输出到 VNC server,而不是默认的显示在 X11 里面。-smb 设置一个通过 SAMBA 服务共享的文件夹。-redir 设置端口映射,这可以把发送到主机的请求转移到 VM 上。-kernel、-append 和 -initrd 可以设置一个独立的 Linux 内核用于 boot 一个 /。串口通过 -serial 映射,它可以把很多东西当作是 VM 的串口,如 TCP/IP 的连接。
在虚拟机里面可以用 C-M-1、2、3 在 QEMU 的 虚拟界面、moniter 和 serial port 之间切换。在 monitor 里面可以执行需要的命令控制虚拟机的行为(请参看 QEMU 的 user doc),如 commit 和 -snapshot 合用,可以需要的时候把镜像写入磁盘文件;通过 info 查看 network、block、registers 等;quit 退出;change 更改一些参数;screendump 抓屏到 ppm 文件;wavcapture 捕获声音;savevm 和 loadvm 可以保存读取 VM 状态;x、xp 等可以将虚拟机内存中信息 dump 出来;sendkey 像虚拟机发送按键。
说了这么多 manual 里面的东西,下面我们开始配置几台虚拟机玩玩吧。
- 首先尝试一下传说中的 dos 吧,手头是一个 Windows 98 里面的 MS-DOS 7.0 的 img 文件,比如弄个 50Mb 分配给以后的 DOS,首先通过
$ qemu-img create -f qcow2 MS-DOS-7.0.qcow2 50Mb
产生一个会自动增长的 disk file,然后我们通过下面的命令启动qemu -fda PWin98.img -hda MS-DOS-7.0.qcow2 -boot a -m 32 -win2k-hack
可见我们将 Pwin98.img 作为启动盘,分配了 32Mb 内存。可惜这个版本的 DOS 不好用,回头找个好用的 DOS 6.22 还是什么吧,呵呵。 - 我们再来考虑装一个 debian,使用 ISO 镜像。下载 debian 的 netinst 镜像,用下面的命令启动虚拟机开始安装:
qemu -m 128 -cdrom debian-40r0-i386-netinst.iso -hda debian.img -net nic -net user
然后就会像正常安装一样开始安装程序。进行分区什么的,然后配置网络。这里使用的网络是使用用户的网络,如果有 root 权限,可以启用 TAP 等方式,那样甚至可以用虚拟机组成一个网络。 - 这里我们换用网络安装。boot 一个 debian 需要一些东西:不可少的。同时,还必须让 QEMU 拥有
wikipedia 上面对 QEMU 的评价是对 Windows 等 OS 支持不够完整,有些不常用的体系结构支持也不完整,显卡、声卡等驱动支持差,ms 用很老的版本 gcc 编译的 -,-b,其他的一些相关软件将在后面一一了解,我们知道直接做硬件仿真慢,因此 QEMU 有一些加速模块,主要是把一部分应用程序直接在 CPU 上跑,类似 full virtualization 的效果,如 KQEMU(可通过安装 kqemu-modules 包获得)和 QVM86,另外一些虚拟机如 Virtual Box 基本上是利用了 QEMU 关于 i386 虚拟的这部分,加入了自己的一些东西(比较看好这个 Virtual Box,下一个目标,hoho),还有 Xen-HVM、KVM、Darwine、Win4Lin Pro Desktop。
另外 QEMU 提供了一些类似 wine 的 user-space emulation,即直接在当前操作系统中执行代码(不是在虚拟机里面),如 qemu-i386 等,现在仅仅支持 Linux 和 Darwin。kqemu-modules 仅仅对某些操作系统有效。
有一些 QEMU 的前端,如 QEMU launcher 和 Qemulator。