VirtIO实现原理之数据结构与数据传输演示(2)

132 篇文章 41 订阅 yen49.90 yen99.00

接前一篇文章:VirtIO实现原理之数据结构与数据传输演示(1)

本文内容参考:

VirtIO实现原理——vring数据结构-CSDN博客

VirtIO实现原理——数据传输演示-CSDN博客

特此致谢!

一、数据结构总览

2. 相关数据结构

上一回读了《Virtual I/O Device (VIRTIO) Version 1.3》规范的“2.6 Virtqueues”一节中的内容,本回具体讲解其中提到的相关数据结构。再来回顾一下上一回的那3个结构:

为了便于理解,这里还是以老版本进行讲解。先来看一下VirtIO数据结构的总览图:

c4718596b05643f7ba9a3c4e890d8e7a.png

(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结构就讲解完了。下一回继续讲解更多数据结构。