xen的设备I/O环机制

来源:互联网 发布:dock软件iphone6s 编辑:程序博客网 时间:2024/06/05 03:09

xen的设备I/O环机制,旨在提供给guest os高效异步的设备I/O机制.

我们应该知道,xen通过虚拟设备模式,来给guest os提供虚拟的I/O.具体的方式就是,guest os产生I/O请求,然后guest os里面有一个虚拟设备驱动,称为前端,前端将

虚拟请求转发给后端,后端处理完以后,将处理的结果转发给前端.这两步都需要设备I/O机制.

以xen 4.4的源码,我们来分析一下具体的实现

#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \                                                                        \/* Shared ring entry */                                                 \union __name##_sring_entry {                                            \    __req_t req;                                                        \    __rsp_t rsp;                                                        \};                                                                      \                                                                        \/* Shared ring page */             全局的                                     \struct __name##_sring {                                                 \    RING_IDX req_prod, req_event;        //请求的索引,请求的个数,如果为3,3,则1,2,3索引都是请求的并且没有被处理的(提醒后端)                               \    RING_IDX rsp_prod, rsp_event;        //回答的索引,回答的个数,如果为3,3,则1,2,3索引都是回答的并且没有被处理的(提醒前端)                               \    union {                                                             \        struct {                                                        \            uint8_t smartpoll_active;                                   \        } netif;                                                        \        struct {                                                        \            uint8_t msg;                                                \        } tapif_user;                                                   \        uint8_t pvt_pad[4];                                             \    } private;                                                          \    uint8_t __pad[44];                                                  \    union __name##_sring_entry ring[1]; /* variable-length */           \};                                                                      \                                                                        \/* "Front" end's private variables */                                   \struct __name##_front_ring {                                            \    RING_IDX req_prod_pvt;               //标志前端请求到索引数值,如6,表示一直到6的答案是被需要的                               \    RING_IDX rsp_cons;                   //标志收到答案的到了那个索引,如果为4,上面为6,则表示自己还需要5,6的答案,如果两个数值相等则表示所有请求都已经被回答                               \    unsigned int nr_ents;                                               \    struct __name##_sring *sring;                                       \};                                                                      \                                                                        \/* "Back" end's private variables */                                    \struct __name##_back_ring {                                             \    RING_IDX rsp_prod_pvt;               //标志回答到的索引,如果为4,则表示4以前的都提供了回答                               \    RING_IDX req_cons;                   //标志请求的索引,如果读取了请求到的索引,如果为5,则表示把请求读到了5                              \    unsigned int nr_ents;                                               \    struct __name##_sring *sring;                                       \};                                                                      \                                                                        \/* Syntactic sugar */                                                   \typedef struct __name##_sring __name##_sring_t;                         \typedef struct __name##_front_ring __name##_front_ring_t;               \typedef struct __name##_back_ring __name##_back_ring_t

我的理解是I/O环的目的是为了实现异步

怎么实现异步:

I/O环的4个变量分别是 请求的索引,有几个请求,回答了的索引,几个回答
请求的人随便写.只要还有放请求的空间,请求的人只需要记录问题解决到哪儿了就可以了

这句话我们翻译为,前端有请求就可以写入I/O环,只要还有空间,每次写入了,将req_prod_pvt+1,前端可以读取I/O环的回答到哪的索引,进行处理以后,处理一个回答,把rsp_cons+1.

应答的人随便应答,只要还有请求.

后端看I/O里面的请求和自己处理到的请求不一致的时候,就往后面处理,并把结果放在对应的索引中,把自己的处理到和I/O的处理到哪的索引都加1.


我自己觉得也有点混乱了 换一种方式

请求者发请求:

1.req_prod_pvt+1

2.填写ring[req_prod_pvt]

3.req_prod+1

4.req_event+1

请求者读回应:

1.rsp_cons+1

2.读ring[rsp_cons]

3.rsq_event-1

回应者收请求:

1.req_cons+1

2.读ring[req_sons]

3.req_event-1

回应者写回应:

1.rsp_prod_pvt+1

2.写ring[rsp_prod_pvt]

3.rsp_prod+1

4.rsp_event+1


启发就是:以后任何实现异步操作都可以这么做.

思维的过程就是:

发送者,中间人,处理者 

中间人需要记住那几个问题解决了,那几个问题没有解决,哪些问题答案已经被取走了可以完全删除了

采用的方式是 最后一个没有解决的问题和没解决的个数,最后一个没有取走答案的问题,和个数

那么发送者只需要知道那些问题在等待回来答案

处理者需要知道的是我现在处理到哪个问题了.

那么I/O环中前端和后端设备都是冗余的.


0 0
原创粉丝点击