Xen共享环函数释意

很多有关Xen的I/O环的定义在xen/interface/public/io/ring.h文件里,包括许多创建、初始化和使用I/O环的宏。这个通用的接口没有被所有的驱动使用,有两个单向环时驱动会用更简单的机制,其他的也会用更复杂的接口。此处讲述的共享环的宏,网络设备接口和块设备接口都可以使用,请求端和共享端有一对一映射的接口也都能用该宏。很显然,它不适合与控制台,从键盘读取内容并显示到屏幕上是无关的操作。

第一个宏创建环结构,如下所示:

DEFINE_RING_TYPES(name, request_t, response_t);

此宏创建了环结构,请求端是request_t,响应端是response_t结构体。宏表示了三个结构——一个是共享数据结构,它是一个共享页;另外两个包含私有变量,一个是前端的一个是后端的(前端是请求生产者指针和响应消费者指针,后端是请求消费者指针和响应生产者指针),另一个宏会使用这些变量。请求和响应的类型也需要定义,用来将环分为几段,存储请求或是响应。

使用环之前,必须先初始化。为生产者、消费者设置正确的初始值,初始化共享环的宏依赖于函数memset()。因此,即使它没有被优化,也要确保你的内核里有此执行。

为了说明怎么使用这些宏,简洁的看一下虚拟块设备是怎么使用它们的。在io/blkif.h文件里定义了这个设备的接口。块设备接口分别为请求和响应定义了结构体blkif_request、blkif_response,然后定义了共享环结构:

DEFINE_RING_TYPES(blkif, struct blkif_request, struct
    blkif_response);

======================================================================================================

授权表的使用:

为了使用环机制,驱动两端必须能够访问它,也就是说必须共享内存,是通过授权表来共享内存的。n 按规则,Xen分离驱动模型是前端驱动提供授权引用,然后后端驱动映射共享页。也就是说,前端不需要用任何超级调用来建立驱动环。除了一致性,也有一点优势:HVM客户机不需要用授权表超级调用就能实现半虚级化设备驱动。对迁移也有好处,共享环属于前端,后端可以共享它,所以当前端移到不懂的机器上,他们还在相同的地方,能够容易的再映射。

这个规则不仅适用于使用环宏的驱动,对于所有的使用分离模型的Xen驱动,它都适用。也就是说,只有和事件通道相关时,前端驱动才需要用超级调用。

======================================================================================================


上述宏定义了blkif_ring_t类型,表示共享环和其他两个结构(表示前端和后端使用一半共享环的私有变量)。前端必须为共享结构分配空间,然后初始化环。驱动的Linux实现初始化环是:

SHARED_RING_INIT(sring);
FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);

在这里,sring变量是指向共享环结构的指针。info变量是一个指针,指向包含一些内核具体记录有关虚拟块设备的结构体。ring字段是blkif_front_ring_t,它是由环的宏定义的结构体,用来存储有关环前端的私有变量。数据被放入环中需要这些结构。


第一步是向环中写请求,然后,环的请求生产者数量加1。为了提高效率,通常向环中写入多个请求,再执行更行。因此,保留一份私有的请求生产者计数副本是必要的,它让前端知道应该把新请求放在哪,然后把请求放入环中。环中的下一个请求由前端完成:

ring_req = RING_GET_REQUEST(&info->ring, info->ring.
    req_prod_pvt);

然后在请求中填入正确的信息,准备放入前端:

RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);

在这个宏中,notify是一个返回参数,指明前端是否需要向后端传送一个事件。此宏设置共享环的请求生产者计数器等于私有副本计数器的值。然后,它测试请求消费者计数器,如果其值在更新前小于请求生产者计数器的值,表明后端仍然处理更新前在排队的请求。在这种情况下,就不需要向后端发送事件通知,故notify就会被设置为faise。


发送一个请求后,后端处理它并把响应放入环中。获得环中的下一个响应:

blkif_response_t *bret = RING_GETRES_PONSE(&info->ring, i);

这设置bret为环中第i个响应。i的取值在共享环的rsp_prod和rsp_cons取值之间,这两个字段表示响应生产者和消费者的索引。处理响应i后,前端的rsp_cons值指向i。当向环中插入新的请求时使用i,因为它指出该环用此段的后端。获得所有的等待请求后,块驱动执行以下检查:

RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);

如果环仍然有一些请求等待处理,more_to_do值设置为true。检查这个之后,应该使用事件通道,环检查一个最后的时间,然后控制返回。

后端有一个相似的接口,但是使用另一个私有变量结构,使用队列的另一个方法。 
















  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值