2. xenstore结构和通信数据流程
XenStore结构
XenStore包含两个模块:Dom0用户空间的xenstored服务主模块,和Dom*里的XenBus内核模块;此外,还有各种通信接口。各个部分的功能如下:
Xenstored:Dom0用户空间的一个服务,负责管理xenstore的数据(tdb),并且处理所有的请求。
XenBus:内核模块,提供Dom*内核访问xenstore的API,提供用户空间的xenfs接口(/proc/xen/xenbus)。Dom0的Xenbus还要初始化xenstored的运行环境。
共享页面:每一个Domain(包括Dom0自身)都有一个与Dom0通信的共享页面(共享环),这个页面同时被映射到了xenstored的内存空间。也就是说这个页面可以同时被xenstored、dom0内核、和对应的DomU内核读写。Xenstored会随时监控页面,只要环被任意一方更新,xenstored就会直接处理消息,不需要内核模块干预。
Xenstore特殊文件:
文件 | 路径 | 功能 |
xenbus | /proc/xen | XenBus用户接口。用户把请求写入该文件,经由内核发送到共享环 |
以下只在dom0中 |
|
|
tdb | /var/lib/xenstored | xenstore的数据库,存放在dom0的/var/lib/xenstored/tdb,可以用tdbtool打开 |
socket, socket_ro | /var/run/xenstored | Dom0直接操纵xenstored的接口 |
xsd_port, xsd_kva | /proc/xen | 用于Dom0初始化 |
XenStore的通信协议:
Xenstore各个模块间的通信内容——请求和回复——都封装成为一种数据包,格式定义在文件xs_wire.h中。
- struct xsd_sockmsg
- {
- uint32_t type; /* XS_??? */
- uint32_treq_id;/* Request identifier, echoed in daemon's response. */
- uint32_ttx_id; /* Transaction id (0 if not related to a transaction). */
- uint32_t len; /* Length of data following this. */
- /* Generally followed bynul-terminated string(s). */
- };
而共享页面上定义了一个环结构xenstore_domain_interface:
- #define XENSTORE_RING_SIZE 1024
- typedef uint32_t XENSTORE_RING_IDX;
- #define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
- struct xenstore_domain_interface {
- char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
- char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
- XENSTORE_RING_IDX req_cons, req_prod;
- XENSTORE_RING_IDX rsp_cons, rsp_prod;
- };
DomU通信流程
DomU的内核将请求放入共享环,这时Dom0的xenstored会直接检测到这个改变并执行操作,最后把结果返回共享页面。DomU的用户空间需要通过/proc/xen/xenbus来操作xenstore。
DomU向XenStore写入数据的xs_write函数调用流程:
DomU的内核调用流程:
Dom0 User、Kernel 通信流程
Dom0的流程和DomU类似。但是在客户空间,可以通过socket方式直接连接xenstored进行操作,不需要通过xenbus绕圈子。这也就是老版本Xen里面,xs_domain_open和xs_daemon_open的区别。