基于virtio在虚拟机与主机之间传递消息

Virtio是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来传递消息的示意图为:


[img]http://dl.iteye.com/upload/attachment/0081/5476/e7744649-fd3b-36c2-86a7-bed6d7aacbb9.jpg[/img]
以下看虚拟机和主机的相关程序如何构建

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));

4,虚拟机背板程序的部署和更新

随着应用的变化,主机与虚拟机之间的通信模式可能会不断变化,因此虚拟机的背板程序也 需要做相应调整。
相对于每次在主机vmm中打开虚拟机,远程登录虚拟机修改程序,有一种更高效的方式,就是利用qemu-nbd。
qemu-nbd可以将 本地虚拟机镜像文件映射到本地nbd块设备, 将该nbd块设备mount到本地文件系统后,
就可以在虚拟机镜像的文件系统中进行应用程序的部署和更新:

modprobe nbd

qemu-nbd -c /dev/nbd0 image_name

mount /dev/nbd0p1 /mnt/image

通过类似以上操作,/mnt/image目录即虚拟机镜像的文件系统:


[img]http://dl.iteye.com/upload/attachment/0081/5480/6e7533bc-86fe-369b-af2f-7697df245623.jpg[/img]
此后,便可将更新后的背板程序直接部署在虚拟机镜像,比如将启动脚本(包括背板启动程序和模块加载操作)置于虚机镜像文件系统中的/etc/rc.local

更新完后,需要释放nbd相关资源:

umount /mnt/image
qemu-nbd -d /dev/nbd0
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值