UML高级话题¶
在虚拟机之间共享文件系统¶
不要试图仅仅通过从同一个文件启动两个uml来共享文件系统。这与从共享磁盘引导两台物理机器是一样的。它将导致文件系统损坏。
使用分层块设备¶
在两个虚拟机之间共享文件系统的方法是使用ubd块驱动程序的写时复制(COW)分层功能。任何更改的块都存储在私有COW文件中,而读取来自任何设备—如果请求的块在其中有效,则为私有设备,如果无效则为共享设备。使用这种方案,大部分未更改的数据在任意数量的虚拟机之间共享,每个虚拟机都有一个小得多的文件,其中包含它所做的更改。由于大量uml从大型根文件系统引导,这将节省大量磁盘空间。
共享文件系统数据也将有助于提高性能,因为主机将能够使用更少的内存缓存共享数据,因此UML磁盘请求将从主机的内存而不是磁盘提供服务。在多套接字NUMA机器上执行此操作有一个主要警告。在这样的硬件上,使用共享的主映像和COW更改运行许多UML实例可能会导致诸如nmi之类的问题,因为套接字间流量过多。
如果您在像这样的高端硬件上运行UML,请确保使用taskset命令将UML绑定到驻留在相同套接字上的一组逻辑cpu,或者查看一下“调优”部分。
要将写时复制层添加到现有的块设备文件中,只需将COW文件的名称添加到相应的ubd开关中:
ubd0=root_fs_cow,root_fs_debian_22
其中root_fs_cow为私有COW文件,root_fs_debian_22为已存在的共享文件系统。COW文件不需要存在。如果没有,驱动程序将创建并初始化它。
使用磁盘¶
UML具有TRIM支持,它将把磁盘映像文件中任何未使用的空间释放到底层操作系统。使用ls -ls或du来验证实际文件大小是很重要的。
cow有效性¶
对主映像的任何更改都将使所有COW文件无效。如果发生这种情况,UML将不会自动删除任何COW文件,并将拒绝启动。在这种情况下,唯一的解决方案是恢复旧映像(包括其最后修改的时间戳)或删除所有COW文件,这将导致重新创建它们。COW文件中的任何更改都将丢失。
合并COW文件和它的备份文件¶
根据您使用UML和COW设备的方式,建议您每隔一段时间将COW文件中的更改合并到备份文件中。
执行此操作的实用程序是uml_mooo。用法是:
uml_moo COW_file new_backing_file
不需要指定后备文件,因为该信息已经在COW文件头中。如果你很偏执,启动新的合并文件,如果你对它满意,把它移到旧的备份文件上。
默认情况下,uml_mooo创建一个新的备份文件作为安全措施。它还有一个破坏性的合并选项,可以将COW文件直接合并到当前的备份文件中。只有当后备文件只有一个与之关联的COW文件时,这才真正有用。如果有多个奶牛与备份文件相关联,其中一个奶牛的-d合并将使所有其他奶牛无效。但是,如果磁盘空间不足,它会很方便,而且它也应该比非破坏性合并要快得多。
uml_mooo与UML发布包一起安装,并且可以作为UML实用程序的一部分使用。
主机文件访问¶
如果您希望从UML内部访问主机上的文件,您可以将其视为一台单独的机器,并且可以从主机上nfs挂载目录,或者使用scp将文件复制到虚拟机中。然而,由于UML在主机上运行,它可以像任何其他进程一样访问这些文件,并使它们在虚拟机中可用,而不需要使用网络。使用hostfs虚拟文件系统可以实现这一点。有了它,您可以将一个主机目录装入UML文件系统,并像在主机上一样访问其中包含的文件。
没有任何UML映像参数的Hostfs将允许映像挂载主机文件系统的任何部分并对其进行写入。如果运行UML,总是将主机限制在特定的“无害”目录(例如/var/tmp)。如果UML作为根运行,这一点尤其重要。
使用hostfs¶
首先,确保hostfs在虚拟机中可用:
cat /proc/filesystems
主机应该被列出。如果不是,要么重新构建内核,并将hostfs配置到内核中,要么确保将hostfs构建为一个模块并在虚拟机中可用,然后insmod它。
现在你需要做的就是运行mount:
mount none /mnt/host -t hostfs
将主机的/挂载到虚拟机的/mnt/host上。如果你不想挂载主机的根目录,那么你可以使用-o开关来指定要挂载的子目录:
mount none /mnt/home -t hostfs -o /home
将主机的/home挂载到虚拟机的/mnt/home上。
hostfs as the root filesystem¶
可以使用hostfs而不是使用文件中的标准文件系统从主机上的目录层次结构引导。首先,你需要层次结构。最简单的方法是挂载一个现有的root_fs文件:
mount root_fs uml_root_dir -o loop
你需要将etc/fstab中的/文件系统类型更改为’ hostfs ‘,因此该行看起来像这样:
/dev/ubd/0 / hostfs defaults 1 1
然后,您需要拥有该目录中所有由根用户拥有的文件。这对我很有效:
find . -uid 0 -exec chown jdike {} \;
接下来,确保您的UML内核中编译了hostfs,而不是作为一个模块。然后运行UML,引导设备指向该目录:
ubd0=/path/to/uml/root/directory
然后UML应该像往常一样启动。
Hostfs Caveats¶
Hostfs不支持跟踪主机(在UML之外)上的主机文件系统更改。因此,如果一个文件在UML不知情的情况下被更改,UML将不知道它,并且它自己的文件内存缓存可能会损坏。虽然有可能解决这个问题,但目前还没有解决这个问题。
UML调优¶
UML目前是严格的单处理器。但是,它将启动许多线程来处理各种函数。
UBD驱动程序、SIGIO和MMU仿真可以做到这一点。如果系统空闲,这些线程将被迁移到SMP主机上的其他处理器上。不幸的是,这通常会导致较低的性能,因为所有内核之间的缓存/内存同步流量。因此,将UML固定在单个CPU上通常会受益,特别是在大型系统上。在某些基准测试中,这可能导致5倍或更高的性能差异。
类似地,在大型多节点NUMA系统上,如果UML的所有内存都是从它将运行的同一个NUMA节点分配的,那么UML将受益。默认情况下,操作系统不会这样做。为了做到这一点,系统管理员需要创建一个绑定到特定节点的合适的tmpfs ramdisk,并通过在TMP或TEMP环境变量中指定它,将其用作UML RAM分配的源。UML将查看TMPDIR、TMP或TEMP的值。如果失败,它将查找挂载在/dev/shm下的shmfs如果这些都失败了,使用/tmp/,不管它使用的文件系统类型:
mount -t tmpfs -ompol=bind:X none /mnt/tmpfs-nodeX
TEMP=/mnt/tmpfs-nodeX taskset -cX linux options options options..