本文首發於我的公眾號 Linux雲計算網絡(id: cloud_dev),專注於干貨分享,號內有 10T 書籍和視頻資源,后台回復「1024」即可領取,歡迎大家關注,二維碼文末可以掃。
什么是 vhost-user
在 vhost 的方案中,由於 vhost 實現在內核中,guest 與 vhost 的通信,相較於原生的 virtio 方式性能上有了一定程度的提升,從 guest 到 kvm.ko 的交互只有一次用戶態的切換以及數據拷貝。這個方案對於不同 host 之間的通信,或者 guest 到 host nic 之間的通信是比較好的,但是對於某些用戶態進程間的通信,比如數據面的通信方案,openvswitch 和與之類似的 SDN 的解決方案,guest 需要和 host 用戶態的 vswitch 進行數據交換,如果采用 vhost 的方案,guest 和 host 之間又存在多次的上下文切換和數據拷貝,為了避免這種情況,業界就想出將 vhost 從內核態移到用戶態。這就是 vhost-user 的實現。
vhost-user 的實現
vhost-user 和 vhost 的實現原理是一樣,都是采用 vring 完成共享內存,eventfd 機制完成事件通知。不同在於 vhost 實現在內核中,而 vhost-user 實現在用戶空間中,用於用戶空間中兩個進程之間的通信,其采用共享內存的通信方式。
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 會在 guest OS 的內存中創建一個文件,share=on 選項允許其他進程訪問這個文件,也就意味着能訪問 guest OS 內存,達到共享內存的目的。
-netdev type=vhost-user 指定通信方案,file=/path/to/socket 指定 socket 文件。
當 qemu 啟動之后,首先會進行 vring 的初始化,並通過 socket 建立 C/S 的共享內存區域和事件機制,然后 client 通過 eventfd 將 virtio kick 事件通知到 server 端,server 端同樣通過 eventfd 進行響應,完成整個數據交互。
幾個例子
開源社區中實現了一個項目 Vapp,主要是用來測試 vhost-user 的 C/S 模式的,github 地址如下:
https://github.com/virtualopensystems/vapp.git
使用:
$ git clone https://github.com/virtualopensystems/vapp.git
$ cd vapp
$ make
// 運行 server 端
$ ./vhost -s ./vhost.sock
// 運行 client 端
$ ./vhost -q ./vhost.sock
通過以上步驟,就可以啟動 vhost-user 的 C/S 模式。
另外還有例子就是集成在虛擬交換機 Snabbswitch 上的 vhost-user,通過以下方式獲得 vhost-user 分支:
$ git clone -b vhostuser --recursive https://github.com/SnabbCo/snabbswitch.git
$ cd snabbswitch
$ make
測試:
$ sudo src/snabbswitch -t apps.vhost.vhost_user
還有例子就是 qemu 上的實現,這也是最原早的實現,同樣通過以下方式來獲得使用:
$ git clone -b vhost-user-v5 https://github.com/virtualopensystems/qemu.git
$ mkdir qemu/obj
$ cd qemu/obj/
$ ../configure --target-list=x86_64-softmmu
$ make -j
除此之外,還有很多的實現,如 OVS 和 DPDK 上都有實現,這實際上是集成了 vhost-user 的通用 API。
總結
virtio,vhost,vhost-user 是基於場景和性能而提出的三種 guest 和 host 之間的通信方案,三種方案,各有優劣。
vhost-user 用在很多數據面之上的進程間通信,效率高。
我的博客即將入駐“雲棲社區”,誠邀技術同仁一同入駐。
我的公眾號 「Linux雲計算網絡」(id: cloud_dev) ,號內有 10T 書籍和視頻資源,后台回復 「1024」 即可領取,分享的內容包括但不限於 Linux、網絡、雲計算虛擬化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++編程技術等內容,歡迎大家關注。