Cloud Hypervisor 使用 virtio-fs 实现宿主机与虚拟机目录共享:从 virtiofsd 配置到内核挂载全指南
2026/9/17 13:24:35 网站建设 项目流程

Cloud Hypervisor 使用 virtio-fs 实现宿主机与虚拟机目录共享:从 virtiofsd 配置到内核挂载全指南

【免费下载链接】cloud-hypervisorA Virtual Machine Monitor for modern Cloud workloads. Features include CPU, memory and device hotplug, support for running Windows and Linux guests, device offload with vhost-user and a minimal compact footprint. Written in Rust with a strong focus on security.项目地址: https://gitcode.com/GitHub_Trending/cl/cloud-hypervisor

导读

本文介绍如何在 Cloud Hypervisor 中通过 virtio-fs(即 vhost-user-fs)将宿主机目录共享给虚拟机使用。virtio-fs 是由 VIRTIO 规范定义的虚拟设备,它借助 vhost-user 协议把文件系统后端模拟卸载到宿主机上的独立守护进程 virtiofsd 中运行。读完本文,你将掌握 virtiofsd 的构建与运行参数(cache 模式、线程池大小)、Cloud Hypervisor--fs命令行配置(tag、socket、队列参数)、虚拟机内mount -t virtiofs的挂载流程,以及 DAX 特性的可用性边界,并能结合源码理解每个参数背后的校验逻辑与默认值。

virtio-fs 是什么

在虚拟化场景中,宿主机与客户机之间的目录共享一直是高频需求——无论是开发调试、日志收集,还是容器编排中的持久化存储,都需要一种安全、高效、低开销的共享方案。virtio-fs(也称vhost-user-fs)正是为此设计的 VIRTIO 虚拟设备,它允许任意 VMM(虚拟机监视器)提供文件系统共享能力。

它的核心设计在于"前端/后端分离":设备的前端(virtio 队列与 PCI 设备)由 VMM 侧实现,而后端(真实文件系统的 I/O 模拟)则通过vhost-user协议委托给宿主机上一个专用守护进程执行。这种 offload 架构让文件系统实现与 VMM 解耦,也便于复用成熟的 FUSE/文件系统栈。在 Cloud Hypervisor 仓库中,前端设备实现位于 virtio-devices/src/vhost_user/fs.rs,设备类型注册为VirtioDeviceType::Fs,并通过 vmm/src/device_manager.rs 的make_virtio_fs_device()在 VM 启动时实例化。

前置条件

守护进程 virtiofsd

virtio-fs 依赖 vhost-user 协议,即设备模拟(后端)由宿主机上一个专用进程承担,这个进程就是virtiofsd。在启动 Cloud Hypervisor 之前,必须先确保 virtiofsd 已构建并运行在宿主机上。

构建 virtiofsd

git clone https://gitlab.com/virtio-fs/virtiofsd pushd virtiofsd cargo build --release sudo setcap cap_sys_admin+epi target/release/virtiofsd

说明:setcap cap_sys_admin+epi为 virtiofsd 授予必要的CAP_SYS_ADMIN能力,使其能够在宿主机上完成与 VMM 共享内存相关的操作。

创建共享目录

mkdir /tmp/shared_dir

运行 virtiofsd

./virtiofsd \ --log-level debug \ --socket-path=/tmp/virtiofs \ --shared-dir=/tmp/shared_dir \ --cache=never \ --thread-pool-size=$N

几个关键参数说明:

  • --socket-path:vhost-user 的 unix socket 路径,Cloud Hypervisor 侧--fs socket=必须与之一致;
  • --shared-dir:宿主机上要共享出去的目录,例如/tmp/shared_dir
  • --cache:控制宿主页面缓存(page cache)的使用策略;
  • --thread-pool-size:virtiofsd 内部 I/O 线程池大小。
关于--cache模式
  • cache=never是与 Cloud Hypervisor 配合时的默认(推荐)选项。它禁止使用宿主页面缓存,从而降低对宿主机内存的占用,减少"单台宿主机可承载的虚拟机密度"被缓存拖累的风险——这正是"尽可能小 footprint"的体现,有助于在一台宿主机上启动更多虚拟机。
  • cache=always允许使用宿主页面缓存,guest 的工作负载可能获得更好的性能,但代价是宿主机内存 footprint 上升。
关于--thread-pool-size

该参数控制 virtiofsd 派生多少个 I/O 线程。对于 NVMe 这类非常快速的存储,线程数不足会成为瓶颈,只有派生足够的工作线程,才能获得接近原生文件系统的性能。

内核支持

virtio-fs 需要 guest 内核提供virtiofs文件系统驱动。现代 Linux 内核(至少 v5.10)已原生支持 virtio-fs;带额外补丁的旧内核不受支持。同时,Cloud Hypervisor 侧要求 guest 镜像内包含足够新的内核,无论采用直接内核引导(direct kernel boot)还是 EFI 固件引导,都可以配合 virtio-fs 使用。

用 Cloud Hypervisor 共享目录

启动虚拟机

virtiofsd 运行后,在 Cloud Hypervisor 命令行使用--fs选项即可为虚拟机挂载该共享设备。

这里有一个硬性前提:--fs正常工作要求--memory开启shared=on,以便在 virtiofsd(后端进程)与 VMM 之间进行跨进程内存共享。

假设宿主机上已有focal-server-cloudimg-amd64.raw磁盘镜像和vmlinux内核,一个可运行的 Cloud Hypervisor 命令如下:

./cloud-hypervisor \ --cpus boot=1 \ --memory size=1G,shared=on \ --disk path=focal-server-cloudimg-amd64.raw,image_type=raw \ --kernel vmlinux \ --cmdline "console=hvc0 root=/dev/vda1 rw" \ --fs tag=myfs,socket=/tmp/virtiofs,num_queues=1,queue_size=512

其中--fs的参数完整语法(定义于 vmm/src/config.rs 的FsConfig::SYNTAX)为:

tag=<tag_name>,socket=<socket_path>,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,pci_segment=<segment_id>,pci_device_id=<pci_slot>

各参数解析与校验逻辑均可从源码得到印证(vmm/src/config.rsFsConfig::parse/validate):

参数含义默认值与约束
tag共享文件系统的标签,guest 挂载时使用;必填长度不能超过VIRTIO_FS_TAG_LEN(36 字节),超长报ParseFsTagTooLong;该常量定义于 virtio-devices/src/vhost_user/fs.rs
socketvhost-user socket 路径;必填必须与 virtiofsd--socket-path一致;Landlock 沙箱模式下会为它授予rw访问规则(见 vmm/src/vm_config.rsApplyLandlock for FsConfig
num_queues请求队列数量默认1不能超过--cpus boot=指定的 vCPU 数,否则报TooManyQueues
queue_size每个 virtio 队列的项数默认1024;必须是 2 的幂(validate_queue_size),否则报InvalidQueueSize
id设备 ID(可选)缺省时由make_virtio_fs_device()自动生成(前缀见FS_DEVICE_NAME_PREFIX
pci_segment/pci_device_idPCI 段与槽位(可选)用于多 PCI 段拓扑中的设备定位
iommu不支持若开启会返回IommuNotSupported校验错误

默认值定义于 vmm/src/vm_config.rs(default_fsconfig_num_queues() -> 1default_fsconfig_queue_size() -> 1024),并在 vmm/src/config.rs 的parse中通过unwrap_or_else兜底。

队列数量背后的实现细节

从源码看(virtio-devices/src/vhost_user/fs.rsFs::new),实际生效的 virtio 队列数为:

实际队列数 = NUM_QUEUE_OFFSET(1) + num_queues

即除了--fs num_queues=指定的请求队列外,virtio-fs 规范还要求一个额外的队列(通常承载高优先级请求/通知)。同时,设备在协商阶段会通告MQ(多队列)、CONFIGURE_MEM_SLOTSREPLY_ACKINFLIGHT_SHMFDLOG_SHMFDDEVICE_STATE等 vhost-user 协议特性,并会查询后端(virtiofsd)支持的最大队列数;如果请求的队列数超过后端能力,会返回BadQueueNum错误并打印日志vhost-user-fs requested too many queues

另外需要留意:--fs设备默认不开启 vhost-user 直通内存之外的访问平台特性,force_access_platform仅在全局强制时才会置位VIRTIO_F_ACCESS_PLATFORM

在 guest 内挂载共享目录

最后一步是在客户机内部使用virtiofs文件系统类型挂载共享目录:

mkdir mount_dir mount -t virtiofs myfs mount_dir/

其中的tag(此处为myfs)必须与 Cloud Hypervisor 命令行--fs tag=提供的一致,两者对不上将无法正确找到设备。

DAX 特性

virtio-fs 的 DAX(直接访问,将宿主页面缓存以 mmap 方式暴露给 guest,从而让 guest 直接访问文件数据页)特性由于在 virtiofsd 一侧尚未稳定,因此Cloud Hypervisor 中不可用。在 virtio-devices/src/vhost_user/fs.rs 的设备实现中也没有为 DAX 预留共享内存区域——cache字段与get_shm_regions()/userspace_mappings()相关的共享内存能力均围绕通用 vhost-user 机制设计,而非 DAX 缓存窗口。选择cache=never也能进一步降低 host 内存占用,从侧面弱化了在 Cloud Hypervisor 场景下对 DAX 的需求。

更多资源

  • 以 virtio-fs 作为根文件系统启动 guest 的完整示例,可参考 docs/virtiofs-root.md;
  • 若需要了解 Cloud Hypervisor 中其他 vhost-user 后端(块、网络等)的通用协议处理,可阅读 virtio-devices/src/vhost_user/vu_common_ctrl.rs;
  • FsConfig的解析单测(含缺失tag/socket报错、多队列参数解析、非法配置拒绝等场景)位于 vmm/src/config.rs 的fs_fixture及附近测试代码中,可作为排查命令行参数问题的参考。

【免费下载链接】cloud-hypervisorA Virtual Machine Monitor for modern Cloud workloads. Features include CPU, memory and device hotplug, support for running Windows and Linux guests, device offload with vhost-user and a minimal compact footprint. Written in Rust with a strong focus on security.项目地址: https://gitcode.com/GitHub_Trending/cl/cloud-hypervisor

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询