bio与request(io合并与request)

xiaoxiao2021-02-28  77

由“通用块层与bio”我们知道,一次io操作就是一个bio结构,虽然我们的块设备驱动程序完全可以一次处理一个bio请求来执行一次io操作,但这会导致磁盘性能的下降,因为确定bio在磁盘上的起始扇区是很费时的,取而代之的是只要可能,内核就试图把几个相邻扇区的bio合并在一起,这样只用一次寻址。因此引入了一个新的结构request,我们将在后面对该结构进行分析。

当我们要读写一些磁盘数据时,实际上创建一个bio请求,本质上说bio描述的是所请求的扇区以及要对它执行的类型。然而并不是请求一发出就立刻执行——io操作仅仅被调度,执行会向后推迟。这种延迟有利于io合并,是提高块设备性能的关键,当请求传送一个新的数据块时,内核检查能否通过扩展前面处于等待的请求而满足新的请求。

请求描述符request

每个块设备的待处理请求都是用一个请求描述符request来表示的,request结构如下(只列出了较为重要的项):

struct request { union { struct list_head queuelist; //请求队列链表的指针,将在同一请求队列的request链接在一起 struct llist_node ll_list; }; struct request_queue *q; //request所在的请求队列 unsigned int __data_len; /* request传输数据的字节总数 */ sector_t __sector; /*要传送的起始扇区号*/ struct bio *bio; /*请求中第一个没有完成传送操作的bio*/ struct bio *biotail; /*请求链表中最后一个bio*/ struct hlist_node hash; /* merge hash */ struct gendisk *rq_disk; /*请求所对应的磁盘对象*/ struct hd_struct *part; unsigned short nr_phys_segments; /*请求的物理段数(物理内存上不相邻的段数)*/ void *special; char *buffer; /*当前数据传送的内存缓冲区的指针*/ unsigned char __cmd[BLK_MAX_CDB]; unsigned char *cmd; //存放给磁盘适配器的命令的缓冲区 unsigned short cmd_len; //cmd的长度 rq_end_io_fn *end_io; //request完成的回调函数 void *end_io_data; //回调函数的参数 /* for bidi */ struct request *next_rq; }

每个请求包含一个或多个bio结构,bio之间用有序链表连接起来,按bio起始扇区的位置从小到大,而且这些bio之间在磁盘扇区是相邻的,也就是说一个bio的结尾刚好是下一个bio的开头。

最初,通用块层创建一个仅包含一个bio结构的请求。可能存在新bio与请求中已存在的数据物理相邻的情况,就把bio加入该请求,否则用该bio初始化一个新的请求。

转载请注明原文地址: https://www.6miu.com/read-94831.html

最新回复(0)