vhost是virtio的另一种方案,用于跳过qemu,减少qemu和内核之间上下文切换的开销,对于网络IO而言提升尤其明显。vhost目前有两种实现方案,内核态和用户态,本文重点讨论内核态的vhost vhost内核模块主要处理数据面的事情,控制面上还是交给qemu,vhost的数据结构如下 struct vhost_dev { MemoryListener memory_listener; /* MemoryListener是物理内存操作的回调函数集合 */ struct vhost_memory *mem; int n_mem_sections; MemoryRegionSection *mem_sections; struct vhost_virtqueue *vqs; /* vhost_virtqueue列表和个数 */ int nvqs; /* the first virtuque which would be used by this vhost dev */ int vq_index; unsigned long long features; /* vhost设备支持的features */ unsigned long long acked_features; /* guest acked的features */ unsigned long long backend_features; /* backend, e.g. tap设备,支持的features */ bool started; bool log_enabled; vhost_log_chunk_t *log; unsigned long long log_size; Error *migration_blocker; bool force; bool memory_changed; hwaddr mem_changed_start_addr; hwaddr mem_changed_end_addr; const VhostOps *vhost_ops; /* VhostOps基于kernel和user两种形态的vhost有不同的实现,内核的实现最终调用ioctl完成 */ void *opaque; }; struct vhost_virtqueue { int kick; int call; void *desc; void *avail; void *used; int num; unsigned long long used_phys; unsigned used_size; void *ring; unsigned long long ring_phys; unsigned ring_size; EventNotifier masked_notifier; }; vhost的内存布局,也是由一组vhost_memory_region构成, struct vhost_memory_region { __u64 guest_phys_addr; __u64 memory_size; /* bytes */ __u64 userspace_addr; __u64 flags_padding; /* No flags are currently specified. */ }; /* All region addresses and sizes must be 4K aligned. */ #define VHOST_PAGE_SIZE 0x1000 struct vhost_memory { __u32 nregions; __u32 padding; struct vhost_memory_region regions[0]; };
vhost-backend.c kernel_ops
vhost-user.c user_ops
可以看出来一个是内核态用的,一个是给用户态用的(vhost-user,ovs+dpdk)
static const VhostOps kernel_ops = { .backend_type = VHOST_BACKEND_TYPE_KERNEL, .... .vhost_set_mem_table = vhost_kernel_set_mem_table, .vhost_set_vring_addr = vhost_kernel_set_vring_addr, .... } const VhostOps user_ops = { .backend_type = VHOST_BACKEND_TYPE_USER, ... .vhost_set_mem_table = vhost_user_set_mem_table, .vhost_set_vring_addr = vhost_user_set_vring_addr, ...
vhost_set_mem_table 和 .vhost_set_vring_addr非常重要,用来实现共享内存, vhost-user 的基础是 vhost-user进程和QEMU进程之间是通过共享内存的。
https://blog.csdn.net/majieyue/article/details/51262510
原文:https://www.cnblogs.com/dream397/p/13936103.html