https://maggie262.github.io/2020/01/22/vhost/
|------------------------|
| vhost client |---------
|-------------------- | |
| shared memory |----| |
|-------------------- | socket
| | |
| vhost backend |---------
--------------------------
-
vhost-user 基于 C/S 的模式,采用 UNIX 域套接字(UNIX domain socket)来完成进程间的事件通知和数据交互,相比 vhost 中采用 ioctl 的方式,vhost-user 采用 socket 的方式大大简化了操作。
-
vhost-user 基于 vring 这套通用的共享内存通信方案,只要 client 和 server 按照 vring 提供的接口实现所需功能即可,常见的实现方案是 client 实现在 guest OS 中,一般是集成在 virtio 驱动上,server 端实现在 qemu 中,也可以实现在各种数据面中,如 OVS,Snabbswitch 等虚拟交换机。
-
如果使用 qemu 作为 vhost-user 的 server 端实现,在启动 qemu 时,我们需要指定 -mem-path 和 -netdev 参数,如:
qemu -m 1024 -mem-path /hugetlbfs,prealloc=on,share=on -netdev type=vhost-user,id=net0,file=/path/to/socket -device virtio-net-pci,netdev=net0
-
指定 -mem-path 意味着 qemu 会在 host OS 的内存中创建一个文件,share=on 选项允许其他进程访问这个文件,也就意味着能访问 guest OS 内存,达到共享内存的目的。
-
-netdev type=vhost-user 指定通信方案,file=/path/to/socket 指定 socket 文件。
- qemu在初始化vhost-user相关设备时,会通过socket建立Vring和事件通知机制。启动之后Guest和Host通信遵循virtio方式
- qemu中的vhost-user模块将与Guest的握手结果,通过socket通知到宿主机用户态的vhost-backend
- 在guest启动后,加载virtio-net驱动,会写寄存器VIRTIO_PCI_GUEST_FEATURES,这个写操作会被kvm捕获传递给qemu。(qemu又会通知到vhost_backend)
- 当guest中virtio-net加载完成后会写VIRTIO_PCI_STATUS寄存器,这个操作同样会被kvm捕获传递给qemu
- 虚拟机驱动之后,就是host用户态的vhost-backend和Guest中的用户态进程之间的通信了(通过virtio)
- qemu中的vhost-user模块将与Guest的握手结果,通过socket通知到宿主机用户态的vhost-backend
- 通过mmap的方式把ram映射到vhost-user app的进程空间实现内存的共享
支持的vhost消息有
1 2 3 4 5 6 7 |
VHOST_SET_MEM_TABLE
VHOST_SET_VRING_KICK // guest通知后端的ioeventfd
VHOST_SET_VRING_CALL // 设置host用掉buffer时触发的ioeventfd
VHOST_SET_LOG_FD
VHOST_GET_VRING_BASE // 作为信号去数据平面删除vring的一个queue
VHOST_SET_VRING_ERR
...
|