什么是Linux vhost?它是如何实现virtio卸载功能的?
问题解答
1. virtio数据面卸载的实现逻辑
传统virtio半虚拟化数据路径会产生大量用户态<->内核态上下文切换开销:客户机内核读写virtio队列后触发VM退出,宿主机需要把上下文切换到QEMU用户态处理队列数据,再切换回内核态转发流量,全路径开销很高。
vhost协议的卸载本质是把原来QEMU用户态承载的virtio数据面处理逻辑,下沉到宿主机内核模块完成,省掉用户态切换的开销,具体实现分为两个平面:
- 控制面仍保留在QEMU用户态:由QEMU完成和客户机的virtio特性协商、virtqueue内存分配、客户机地址空间到宿主机的映射配置,所有配置信息通过ioctl调用下发给vhost子模块。
- 数据面完全卸载到宿主机内核:客户机触发virtqueue通知后,宿主机内核直接由vhost模块响应,直接读取virtqueue中的IO请求,完成对应转发/处理逻辑后直接通知客户机,全程不需要切入QEMU用户态。
2. vhost.c模块init为空的交互逻辑
你看到的drivers/host/vhost.c是vhost体系的核心公共抽象层,本身不对外提供直接服务,所以不需要在init阶段做任何设备注册、资源初始化动作,空实现是正常的。
它的定位是给具体的业务子模块(比如vhost-net、vhost-scsi、vhost-vsock等)提供通用能力,会导出vhost_dev_init、vhost_vq_process等内核符号给子模块调用,所有对外交互入口都在具体子模块侧:
- 具体vhost子模块加载时,会注册对应的字符设备(比如vhost-net会生成
/dev/vhost-net) - QEMU等上层组件通过打开对应字符设备、调用ioctl的方式和vhost体系交互,所有请求最终会由子模块转发到vhost核心层的通用逻辑处理。
- 客户机侧的vhost-net前端驱动和宿主机vhost模块之间没有直接通信,所有的控制信息交互还是走QEMU的virtio模拟通道,数据面通过共享的virtqueue内存直接交互。
内容的提问来源于stack exchange,提问作者Rafaelo
相关产品推荐
相关产品推荐

