接前一篇文章:VirtIO实现原理之数据结构与数据传输演示(3)
本文内容参考:
特此致谢!
一、数据结构总览
2. 相关数据结构
前文书介绍了《Virtual I/O Device (VIRTIO) Version 1.3》规范的“2.6 Virtqueues”一节中提到的相关数据结构。再来回顾一下那3个结构:
为了便于理解,这里还是以老版本进行讲解。先来看一下VirtIO数据结构的总览图:
(3)已用环(Used Ring)
存放Decriptor Table索引,指向Descriptor Table中的一个entry。当Host根据Avail Ring中提供的信息从VRing中取出buffer,处理完之后,更新Used Ring,把这一次处理的Descriptor chain头部的地址放到Used Ring中。Host每取一次buffer,就将Used Ring的idx加1,以表示自己工作在Used Ring中的哪个位置。Used Ring由Host维护,提供给Guest用。
已用环(Used Ring)对应的结构为struct vring_used。struct vring_used的定义在QEMU源码中有不止一处(qemu-8.1.4版本一共3处),这里以roms/u-boot/include/virtio_ring.h中的为例,代码如下:
struct vring_used_elem {
/* Index of start of used descriptor chain */
__virtio32 id;
/* Total length of the descriptor chain which was used (written to) */
__virtio32 len;
};
struct vring_used {
__virtio16 flags;
__virtio16 idx;
struct vring_used_elem ring[];
};
Host通过Used Ring向Host提供信息,指示Host处理buffer的位置。
成员说明
- __virtio16 flags
用于指示Guest当它添加完buffer,将Descriptor index写入Avail Ring之后,是否发送notification通知Host。如果flags设置为0,Guest每增加一次buffer就会通知Host;如果flags为1,不通知Host。Used Ring flags的含义和Avail Ring flags的含义类似,都是指示前后端数据处理完后是否通知对方。同样的,当VIRTIO_F_EVENT_IDX特性开启时,flags必须被设置成0,Guest使用avail_event方式通知Host。
- __virtio16 idx
指示Host下一次操作的buffer在Used Ring所的位置。换句话说,idx存放的是ring数组索引,ring[idx]存放的才是下一次操作的buffer头在Descriptor Table的位置。
- struct vring_used_elem ring[]
存放Descriptor Table索引的环。意义与Avail Ring中的ring类似,都是存放指向Descriptor Table的索引。但与Used Ring不同的是,它的元素还增加了一个len字段,用来表示Host在buffer中处理了多长的数据。这个字段在某些场景下有用。
至此,第3个数据结构——已用环(Used Ring)对应的vring_used结构就讲解完了。下一回继续讲解更多数据结构。