接前一篇文章:VirtIO实现原理之数据结构与数据传输演示(1)
本文内容参考:
特此致谢!
一、数据结构总览
2. 相关数据结构
上一回读了《Virtual I/O Device (VIRTIO) Version 1.3》规范的“2.6 Virtqueues”一节中的内容,本回具体讲解其中提到的相关数据结构。再来回顾一下上一回的那3个结构:
为了便于理解,这里还是以老版本进行讲解。先来看一下VirtIO数据结构的总览图:
(1)描述符表(Descriptor Table)
Destriptor Table中存放Guest Driver(客户机驱动,前端驱动)提供的buffer的指针,每个条目指向一个Guest Driver分配的收发数据buffer。注意:VRing中buffer空间的分配永远由Guest Driver负责,Guest Driver发数据时,还需要向buffer填写数据;Guest Driver收数据时,分配buffer空间后通知Host向buffer中填写数据。
Descriptor Table中存放的是一个一个的vring_desc结构(实例),所有的vring_desc(实例)组成了一个Descriptor Table。Descriptor Table的条目数就是virtqueue的队列深度,表示Guest 一次性最多可以存放的数据buffer,QEMU默认设置为128。
由此引出来数据结构struct vring_desc。struct vring_desc的定义在QEMU源码中有不止一处(qemu-8.1.4版本一共3处),这里以roms/u-boot/include/virtio_ring.h中的为例,代码如下:
/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
struct vring_desc {
/* Address (guest-physical) */
__virtio64 addr;
/* Length */
__virtio32 len;
/* The flags as indicated above */
__virtio16 flags;
/* We chain unused descriptors via this, too */
__virtio16 next;
};
vring_desc结构是一个buffer描述符,可以认为它代表了一个Guest内存的buffer。指向要传输的数据。
成员说明
- __virtio64 addr
数据的物理地址。
- __virtio32 len
数据的长度。
- __virtio16 flags
标记数据对于Host是可读还是可写,如果buffer用于发送数据,对Host只读;否则,对Host只写。
flags的取值如下(next同文件中):
/* This marks a buffer as continuing via the next field. */
#define VRING_DESC_F_NEXT 1
/* This marks a buffer as write-only (otherwise read-only). */
#define VRING_DESC_F_WRITE 2
/* This means the buffer contains a list of buffer descriptors. */
#define VRING_DESC_F_INDIRECT 4
VRING_DESC_F_NEXT:表示该buffer之后还有buffer,所有buffer可以通过next连成一个descriptor chain。
VRING_DESC_F_WRITE:表示该buffer只能写,当buffer用于接收数据时,需要向Host提供buffer,这个时候就标记buffer为写;反之是发送数据,标记为读。
VRING_DESC_F_INDIRECT:表示该buff包含一个buffer描述符的链表。
- __virtio16 next
存放下一个buffer在Descriptor Table的位置。
注意,next不是存放的物理地址。通过其类型不难判断,next是存放的下一个buffer在Descriptor Table的索引。
至此,第1个数据结构——Descriptor Table及其背后实际的vring_desc结构就讲解完了。下一回继续讲解更多数据结构。