请求队列request_queue
请求队列是由一个大的数据结构request_queue表示的。
struct request_queue {
struct list_head queue_head; //待处理请求的链表,请求队列中的请求用链表组织在一起
struct request *last_merge; //指向队列中首先可能合并的请求描述符
struct elevator_queue *elevator;//指向elevator对象的指针(电梯算法)
struct request_list root_rl;///为分配请求描述符所使用的数据结构
request_fn_proc *request_fn;//实现驱动程序的策略例程入口点的方法,由他处理队列中请求
make_request_fn *make_request_fn;//将一个新请求插入请求队列时调用的方法
prep_rq_fn *prep_rq_fn; //该方法把这个处理请求的命令发送给硬件设备
softirq_done_fn *softirq_done_fn;
rq_timed_out_fn *rq_timed_out_fn;
sector_t end_sector;
struct request *boundary_rq;
struct delayed_work delay_work;
struct backing_dev_info backing_dev_info;
/*
* The queue owner gets to use this for whatever they like.
* ll_rw_blk doesn't touch it.
*/
void *queuedata;
spinlock_t __queue_lock; //请求队列锁
spinlock_t *queue_lock; //指向请求队列锁的指针
unsigned long nr_requests;/* 请求队列中允许的最大请求数 */
struct queue_limits limits;//队列的其他限制
};
该结构是串联整个块设备驱动的核心,下面列举几个特别重要的元素:
- request_fn_proc *request_fn; 它是实现驱动程序的策略例程入口点的方法,由他处理队列中请求,我们所写的块设备驱动程序的核心就是它的请求处理函数(request_fn)。
- make_request_fn *make_request_fn;将一个新请求插入请求队列时调用的方法,块设备的io调度程序主要是在该函数内完成。
- struct elevator_queue *elevator;指向elevator对象的指针(电梯算法),决定了io调度层使用的io调度算法。
请求队列是一个双向链表,其元素就是请求描述符(也就是request数据结构)。请求队列描述符中的queue_head字段存放链表的头(第一个伪元素),而请求描述符中queuelist字段的指针把任一请求链接到链表的前一个和后一个元素之间。
队列链表中元素的排序方式对每个块设备驱动程序是特定的;然而,I/O调度程序提供了几种预先确定好的元素排序方式,牵涉到“I/O调度算法”的概念。
我们通过一个图把前面的知识串联起来: