其他分享
首页 > 其他分享> > VIRTIO & VHOST

VIRTIO & VHOST

作者:互联网

在虚拟化领域,virtio 随处可见。当前,virtio 可以加速 IO、network子系统。

在 IO 子系统,主要有 virtio-blk, virtio-scsi。同时,有 vhost 相关的 vhost-blk, vhost-scsi, vhost-nvme 这些。

看起来东西很多很乱,其实只要理解了本质,就可以轻松化解如此多virtio*让人困扰的问题了。

本质是什么呢?本质就是 virtio 的数据结构,以及操作。

virtio基本结构

virtio 的基本数据结构是一个 ring,这个 ring 是一段连续的内存。有了一段内存,就可以为所欲为了。

virtio 把这段内存分成3个部分,依次是 desc,avail,used。每一块是一个数组,可以顺序索引。他们的元素个数是一样,也就是是 ring 的 长度。

 

virtio & vhost数据流动

以VHOST为例,来解释一下数据是如何流动的:

Vhost是什么

virtio offload到host叫做vhost。可以在内核态或者用户态实现。在内核态的实现主要在Linux的kernel实现。

kernel代码位置:drivers/vhost Vhost作为字符设备使用,来与qemu进行交互。跟其他的很多driver一样,利用ioctl。vhost-net 驱动会创建一个名为 /dev/vhost-net 的字符型设备,当 QEMU 通过-netdev tap,fd=,id=hostnet0,vhost=on,vhostfd=这样的参数启动时,QEMU 会打开这个设备(你可以通过 lsof -p $PID 查看,$PID 为 QEMU 的进程号)并通过 ioctl 初始化设备。

初始化过程中 vhost 驱动会创建一个内核线程名为 vhost-$PID ($PID 为 QEMU 的进程号),这个线程是 vhost 的工作线程(worker thread),工作线程会始终等待 virtqueue 触发,然后处理 virtqueue 上的 buffer,然后送到 tap 设备的文件描述符。反过来,文件描述符的 polling 也是由工作线程完成的,也就是说 vhost-net 在内核模拟了 tx、rx 队列,而并没有完成整个 virtio PIC 设备的模拟,控制平面例如在线迁移、协商等依旧由 QEMU 实现。

 

 

Vhost-user与vhost的区别

Vhost是client与kernel(server)的交互,client与内核共享内存,局限性是如果client要发送消息到用户进程,很不方便; Vhost-user使用unix domain来进行通信,两个用户进程共享内存,达到和vhost一样的效果。

Virtio-blk与virtio-scsi

他们都是在 virtio spec 里面定义的两种块设备实现。区别是 virtio-blk 是作为 pci 设备挂在 qemu 里面,所以最多只能有16块 virtio-blk 盘。 而 virtio-scsi 作为 scsi 子系统,挂在 scsi 总线上,数量上可以多得多。由于 virtio-scsi 实现了 scsi 的协议 ,所以复杂度来说要高一些。 此时,在 qemu 里面看,这块盘跟普通的 scsi 盘一样,支持 scsi 命令查询,例如 sg3_utils 提供的工具。但是 virtio-blk 盘不支持 scsi 命令。

相关代码:

Kerne
drivers/vhost/vhost.c - common vhost driver code
drivers/vhost/net.c - vhost-net driver
virt/kvm/eventfd.c - ioeventfd and irqfd

Qemu
hw/vhost.c - common vhost initialization code
hw/vhost_net.c - vhost-net initialization

# ps -ef | grep kvm1
libvirt+      3549     1  87 ?        00:22:09 qemu-system-x86_64 -enable-kvm -name kvm1 ... -netdev tap,fd=26,id=hostnet0,vhost=on,vhostfd=28 ...

可以看到,其中网络部分参数,-netdev tap,fd=26 表示的就是连接主机上的 tap 设备。

创建的 fd=26 为读写 /dev/net/tun 的文件描述符。

使用 lsof -p 3549 验证下:

# lsof -p 3549
COMMAND    PID USER   FD      TYPE             DEVICE    SIZE/OFF     NODE NAME
...
qemu-system 3549  libvirt-qemu   26u      CHR             10,200         0t107    135 /dev/net/tun
...

可以看到,PID 为 3549 的进程打开了文件 /dev/net/tun,分配的文件描述符 fd 为 26。

因此,我们可以得出以下结论:在 kvm 虚机启动时,会向内核注册 tap 虚拟网卡,同时打开设备文件 /dev/net/tun,拿到文件描述符 fd,然后将 fd 和 tap 关联,tap 就成了一端连接着用户空间的 qemu-kvm,一端连着主机上的 bridge 的端口,促使两者完成通信。

 

标签:virtio,idx,vhost,used,client,avail,VHOST,VIRTIO
来源: https://www.cnblogs.com/dream397/p/13867557.html