Virtio-vsock Device + aF_UNIX 套接字通信

irtio是Linux虚拟机平台上统一的虚拟IO接口驱动。通常主机为了让客户机像在真实环境中一样运行,需要为客户机创建各式各样的虚拟设备,
如磁盘,网卡,显卡,时钟,USB 等。这些虚拟设备大大降低了客户机的性能。使用virtio。虚拟机guest不用关注如何创建各种虚拟硬件设备
(如磁盘,网卡,显卡等),可以用统一的虚拟设备,因此大大提高虚拟机的性能。这个统一的虚拟设备就是virtio。

关于virtio原理以及在kvm和libvirt中的使用,可以参考:

理解Virtio的原理:http://www.ibm.com/developerworks/cn/linux/l-virtio/

Virtio在kvm中的使用:http://www.linux-kvm.org/page/Virtio

Virtio在libvirt中的使用:http://wiki.libvirt.org/page/Virtio

本文会侧重于virtio一个有趣的应用:如何使用virtio在虚拟机guest和主机host之间传递消息。这里的消息既包括控制指令,也包括文件传输(比如通过主机向虚拟机传递脚本的场景)。使用virtio传递消息有两点优势:

1,对虚拟机和主机的网络设置没有任何要求

2,效率更高

使用virtio来传递消息的示意图为:


 

 


以下看虚拟机和主机的相关程序如何构建

1,通过libvirt在虚拟机创建时启动virtio通道

以上图中启动两个virtio通道为例(数据通道和控制通道),libvirt启动配置xml中需要加入:

<channel type=’unix’>

<source mode=’bind’ path=’vm.ctl’/>

<target type=’virtio’ address=’virtio-serial’ port=’0′/>

</channel>

<channel type=’unix’>

<source mode=’bind’ path=’vm.data’/>

<target type=’virtio’ address=’virtio-serial’ port=’1′/>

</channel>

<controller type=’virtio-serial’ index=’0′ ports=’16′/>

 




1)vm.ctl与vm.data为两个virtio通道在主机本地的映射节点文件,主机应用可以基于这两个映射文件通过unix sock实现与虚拟机的通信

2)index=’0′ ports=’16′表示使用的是virtio的0号总线,这个总线总共可以开辟16个虚拟端口

3)port=’0′和port=’1′表示两个virtio通道对应在虚拟机的端口号

虚拟机启动后,在虚拟机操作系统中可以发现两个新的字符设备

/dev/vport0p0,对应控制通道

/dev/vport0p1,对应数据通道

对应xml中的定义,vport0表示使用的是0号virtio总线,p0和p1则分别对应每个通道指定的端口号。虚拟机中对这两个字符设备的读写操作即相当于对virtio通道的读写,以此可以实现与主机的通信。

2,虚拟机端的背板程序(back-end app)

在上面xml定义的应用场景,虚拟机中会发现两个新的字符设备,其中/dev/vport0p0对应控制通道,/dev/vport0p1对应数 据通道。虚拟机中的背板程序是一个运行于虚机os的后台进程,基于poll(没有并发需求,使用poll即可)对控制端口/dev/vport0p0进行 异步监听,读取主机向控制通道发送的请求,并完成响应。为充分利用虚拟机资源,数据端口/dev/vport0p1在背板程序中初始是关闭的,当主机需要 向虚拟机传递文件时,首先通过控制通道向虚拟机的背板程序发送请求,虚拟机背板程序异步监听到该请求后,打开/dev/vport0p1数据端口,数据传 输完毕后,背板程序会重新关闭该端口。

对于部分虚拟机的os,可能没有默认加入virtio的支持,因此需要在启动背板程序前加载相关模块:

insmod virtio.ko

insmod virtio_ring.ko

insmod virtio_pci.ko

insmod hvc_console.ko

insmod nscatterlist.ko

insmod virtio_console.ko

下面的链接中包括一个不错的背板程序的示例:(此链接可能失效,大家自己去找找!)

http://fedorapeople.org/gitweb?p=amitshah/public_git/test-virtserial.git;a=blob;f=auto-virtserial-guest.c;hb=HEAD

3,主机端的应用程序

由于virtio通道通过libvirt启动配置xml中的相关定义,在host本地映射为两个文件,主机程序可以通过unix套接字的方式对virtio通道进行读写,实现与虚拟机的消息数据传递:

sock = socket(AF_UNIX, SOCK_STREAM, 0);

sockaddr_un.sun_family = AF_UNIX;

memcpy(&sockaddr_un.sun_path, “vm.ctl”, sizeof(sockaddr_un.sun_path));

connect(sock, sockaddr_un, sizeof(sockaddr_un));

posted on 2020-10-23 20:15  tycoon3  阅读(2076)  评论(0编辑  收藏  举报

导航