分类: LINUX
2007-11-18 23:13:34
你可以使用(UML)在Linux内(主机Linux内核)以用户态方式运行Linux(内核), 你还可以在单个计算机上运行多个独立的虚拟计算机. 下面我们来了解UML的功能和如何使用它更方便地调试内核.
在UML环境中, 每一个虚拟机都能够运行自己的, 比如不同的Linux发行版和内核. 你也可以在主机系统上定制虚拟机程序, 而且每一个虚拟机都完全隔离. 另外, UML可以用于提高受感染系统的安全性, 开发人员和系统管理员可用于开发和测试的沙盒, 你还可以使用自己熟悉的用户空间工具来进行内核调试, 比如用户空间程序gdb.
使用UML
的”开始”栏目介绍了UML技术, 如何下载和运行预编译的UML客户机内核和1.6GB(80MB压缩)大小的 5根文件系统.
UML使用起来很方便, 不像其它的虚拟软件如和, 你可以在普通的主机内核上运行UML. 不过当你看完文章的后半部分, 你会考虑给主机内核打上补丁, 然后再运行UML. 首先我们了解”开始”栏目中的一些命令:
./linux-2.6.19-rc5 ubda=FedoraCore5-x86-root_fs mem=128M
你正在运行UML客户机内核程序(Linux-2.6.19-rc5), 从命令行运行的程序和UML客户机内核程序都是用户空间进程. 注意UML客户机内核是经过专门编译的, 所以你才能够从命令行运行它. 如果你尝试从命令行运行一个普通(未修改)的Linux内核, 内核不会工作. 我将在下面介绍如何构建UML客户机内核.
mem参数指定了虚拟机的可用内存数. 注意mem的大小可大于机器物理内存的总大小, 因为虚拟机还可以使用主机的虚拟内存.
不过自从主机上的UML内核是一个标准的用户进程, 进程的地址空间大小有了一定的限制. x86平台的上限值是3GB.
命令行中的ubda参数指定了UML内核的文件名, 文件名将用于创建虚拟机的/dev/ubda虚拟块设备. 虚拟块设备有自己的根文件系统. /dev/udba虚拟块设备是虚拟机的第一个块设备, 同linux主机系统的第一个物理块设备/dev/hda类似.
在本实例中, 你创建了一个虚拟块设备/dev/ubda, 它的所有数据来自于一个包含了Fedora Core 5根文件系统的文件. UML系统将使用该文件系统进行系统引导. 你可以指定多个块设备, 而不一定都需要是文件系统. 比如, 你也许想创建一个用于swap交换分区的/dev/ubdb设备. 这样做, 在运行你的UML内核之前, 在主机系统上创建一个文件:
dd if=/dev/zero ōf=swap bs=1M count=128
命令创建了一个128MB大小的文件. 然后使用ubdb参数启动UML内核:
./linux-2.6.19-rc5 ubda=FedoraCore5-x86-root_fs ubdb=swap mem=128M
虚拟机运行后, 你被提示有两个块设备:
[root@localhost ~]# ls -l /dev/ubd*
brw-r—– 1 root disk 98, 0 Dec 14 02:19 /dev/ubda
brw-r—– 1 root disk 98, 16 Dec 14 02:19 /dev/ubdb
先指定/dev/ubdb为交换空间, 然后确认交换分区:
[root@localhost ~]# mkswap /dev/ubdb
Setting up swapspace version 1, size = 134213 kB
[root@localhost ~]# swapon /dev/ubdb
[root@localhost ~]# swapon -s
Filename Type Size Used Priority
/dev/ubdb partition 131064 0 -1
如果你想更改主意, 指定/dev/ubdb使用ext3文件系统, 这样做:
[root@localhost ~]# swapoff /dev/ubdb
[root@localhost ~]# mkfs.ext3 /dev/ubdb
…
[root@localhost ~]# mkdir /mnt/ubdb
[root@localhost ~]# mount /dev/ubdb /mnt/ubdb
[root@localhost ~]# ls -l /mnt/ubdb
total 12
drwx—— 2 root root 12288 Dec 14 02:22 lost+found
虚拟块设备也可以指向到主机系统的物理块设备. 比如, 当你指定ubdb=/dev/cdrom后, 在虚拟机中, 虚拟机UML内核可以访问主机上的CDROM设备.
在主机上也可以指定一个tar文件做为虚拟机的一个块设备. 当启动UML内核的时候, 指定ubdb=hello.tar, 然后在虚拟机上使用命令tar -xf /dev/udbd解开tar文件的内容. 这是一个从主机拷贝数据到虚拟机的简单办法.
写时拷贝(Copy-One-Write, COW)
想象一下, 你有多个非常相似的虚拟机. 你希望它们共同使用一个根文件系统镜像, 显然这样可以节省大量的磁盘空间. 如果你仔细考虑后, 这不是一个很好的主意, 因为所有机器都会向共享的镜像写入数据, 从而会影响其它的机器(存在竞争的问题). 所以, 你会考虑每一个虚拟机都有自己可写入的文件系统, 但是这样会浪费很多磁盘空间. 而且你还需要给每一个机器分别进行文件拷贝. 此外, 每一个文件可能非常相似, 仅仅是一些非常次要的差别.
UML使用写时拷贝(Copy-on-write, COW)解决了这个问题. 基本的原理是你可以使用两个文件来创建一个虚拟块设备: 一个是只读的, 包含了所有的共享数据. 另外一个可读而且可写, 存储了所有的修改记录. 当启动UML内核的时候, 指定ubdb=cowfile,sharedfile, 这样你创建了一个/dev/ubdb设备, 所有的修改都将保存到一个叫做cowfile的文件, 当sharedfile用于更大的共享只读数据. 一件重要的事情是记住cowfile文件是一个稀疏文件(实际上它只占用了很少的存储空间); 起初cowfile看起来跟shared文件一样大, 但是使用ls -ls, 你将看到事实上它没有那么大:
host% ls -lsh cowfile
2.9K -rw-r–r– 1 marc marc 1.6G Dec 22 16:58 cowfile
首次cowfile文件看起来有1.6GB, 但是注意看第一栏, 你将看到磁盘实际占用的字节数仅为2.9KB. 我没有做过cow文件系统的性能测试. 但是从理论上, COW提高了存取性能. 主机系统将不用再存储两份同样的数据拷贝, 从而节省了物理空间.
更多COW相关的信息, 请查阅UML网站上的页面.
使用hostfs从虚拟机存取物理主机上的文件
从虚拟机存取物理主机上的文件, UML提供了少数的几个方法. 最简单的方法是使用hostfs. 在客户机上运行下面的命令, 虚拟机可以通过/host目录访问整个主机的文件系统:
mount -t hostfs none /host
下面是一个相对更复杂的例子: 如何在主机文件系统上加载一个指定的目录.
mount -t hostfs none /home/marc -o /home/marc
hostfs存在一些限制. 另外还有一个方法叫做humfs, 它解决了限制方面的问题. 更多hostfs和humfs的详细信息, 请查阅UML网站的页面.
构建自己的UML客户机内核
到现在为止, 我仅仅介绍了如何通过下载UML客户机内核的方式使用UML. 当然你还可以构建自己的UML客户机内核. 现在如果你使用的是最新的Linux内核版本, 主机linux内核的编译将十分简单.
你可以选择从kernel.org网站下载Linux内核源代码, 或者你也可以选择从自己Linux发行版的安装光盘或网站来获得内核源代码. 注意使用Linux内核2.6.9和最新的内核版本. 因为2.6.9和最新的内核版本包含了UML代码, 所以可以很方便地构建UML客户机内核,
对于老的内核版本, 你需要下载和打上合适的补丁. 可能的话最好选择最新的内核版本. 你可以使用unzip或tar来解压内核源代码. 在编译UML客户机内核之前, 在make命令中增加ARCH=um选项. 比如, 下面是编译UML缺省内核的命令步骤, 首先定制参数, 然后编译UML内核:
make defconfig ARCH=um
make menuconfig ARCH=um
make ARCH=um
编译好内核后, 你有了一个大的可执行文件”linux”. 文件非常大, 因为它包含了调试字符. 如果你不打算使用调试程序, 你可以减小内核文件的大小, 使用strip命令去掉调试字符. 然后运行新的UML内核, ./linux命令后面使用了ubda=参数(指定一个文件, 文件包含了根文件系统)的. 比如:
./linux ubda=FedoraCore5-x86-root_fs
更多构建UML内核的详细信息, 请查阅UML网站的页面.
内核地址空间隔离补丁(SKAS patch)
甚至是早期的UML版本, 主机内核不需要额外的支持就能在线程跟踪(Tracing Thread)模式下运行客户机内核. 然而, TT模式的缺点会影响到UML的安全和性能. 为了解决这个问题, UML作者Jeff Dike为主机内核开发了一个补丁, 它允许UML运行在一个更高级的模式, 内核地址空间隔离(SKAS)模式, 现在统称为SKAS3模式.
一段时间里, TT和SKAS3模式是仅有的两个选择, 不过SKAS3模式被广泛认为是其中最好的模式. 所以如果你打算用UML执行某些关键的任务, 最好给你的主机内核打上SKAS3补丁. TT和SKAS3模式的更多介绍, 请查阅UML网站的页面.
最近, Dike为UML客户机内核开发了一个叫做SKAS0的补丁. 与TT模式相比较, SKAS0使客户机内核具有了更好的性能和安全性, 而且不用给主机内核打补丁. 因为从Linux 2.6.13内核开始, Linux内核增加了SKAS0补丁. 所以如果你使用了最新的内核, 你可以直接在SKAS0模式运行你的UML客户机内核. 当你的UML客户机内核引导的时候, 屏幕最上端会显示:
Checking for the skas3 patch in the host:
- /proc/mm…not found
- PTRACE_FAULTINFO…not found
- PTRACE_LDT…not found
UML running in SKAS0 mode
上面显示UML没有在主机内核中发现SKAS3补丁, 然后进入到SKA0模式. 这不是一件坏事, 因为SKAS0模式要好于TT模式. 虽然SKAS3模式比SKAS0模式有更好的性能和安全性. 如果你打算继续使用UML执行重要的任务, 选择SKAS3补丁是值得的. Dike还提到可能会开发SKAS4补丁, 也许你看到这里的时候SKAS4已经提供下载.
虽然UML是一个发展很快的技术. 不过网站上一些文档已经过时. 特别是我在写这篇文章的时候, 网站上的SKAS模式页面没有介绍SKAS0模式. 我希望当你读到这里时候, 文档已经更新.
对于SKAS0模式, 如Dike的中所解释, 已经发送到Linux内核.
创建自己的根文件系统
使用UML的最简单方式是下载预编译的根文件系统, 比如网站提供的文件系统. 不过最终, 你会创建自己的根文件系统.
UML网站的”“页面介绍了很多用于构建根文件系统的辅助工具. 比如, , 和.
连网你的客户机
在某些情况下, 你需要为你的UML客户机创建一个连网的环境. 方式有很多种, 主要还是看你的网络配置. 但最简单的方法是客户机通过接口连接到主机, 然后在客户机上创建一个虚拟的eth0接口.
如果你的主机Linux内核已经支持TUN/TAP(或者你已有tun.ko内核模块, 直接运行modprobe tun加载), 你可以使用UML tunctl工具在主机上创建一个TAP接口. 然后使用ifconfig配置一个IP地址.
为了最终建立客户机网络, 你可以增加eth0=tuntap,,,
客户机上的eth0接口创建好后, 你需要给接口分配一个IP地址(或者通过DHCP获得), 然后你可能会使用route命令为新接口配置一个缺省的路由. 根据你的网络配置情况, 你还可能需要在主机上打开IP转发或者使用iptables建立转发策略.
在你的UML客户机上运行X程序
你可能会疑惑可否在UML客户机上运行X程序, 当然可以. 一旦建立好网络, 你可以在客户机上设置DISPLAY环境变量, 然后在客户机上运行X程序. 这样可能会很不错. 不过你有可能只需要在客户机上运行少数的X程序; 你需要完整的桌面环境, 比如GNOME或KDE. 这似乎也没有问题. 你可以在客户机上运行Xnest程序. Xnest不但能够做为主机X服务器的客户端而且还能够做为客户机的X服务器程序. 比如, 在客户机上运行GNOME桌面, 你可以从主机窗口看到客户机的GNome桌面:
%guest Xnest :1 &
%guest gnome-session –display=:1 &
结论
你可以使用UML创建完全独立的虚拟机, 而且每个虚拟机都有自己的Linux内核. 你也可以使用UML提高系统的安全性, 因为物理机上的服务器进程是完全隔离的. 你也可以用于模拟开发和生产环境, 甚至可以向用户提供虚拟机root帐户. 你也可以用于测试新的软件而不用担心会影响到你的系统.
备注
是我实际使用过的一个Linode虚拟服务器提供商. 虽然价格偏高, 不过售后支持, 社区, 还有系统的稳定性, 安全性和可管理性都很不错.
参考