unsigned int timeout; //请求的超时
int retries;
rq_end_io_fn *end_io;
void *end_io_data;
};
每个request请求包含一个或多个bio结构。最初,通用块层创建一个仅包含一个bio结构的请求。然后,I/O调度程序要么向初始的bio中增加一个新段,要么将另一个bio结构链接到请求中,从而“扩展”该请求,原因是可能存在新数据与请求中已存在的数据物理相邻的情况。请求描述符的bio字段指向请求中的第一个bio结构,而biotail字段则指向最后一个bio结构。rq_for_each_bio宏执行一个循环,从而遍历一个请求(而不是请求队列)中的所有bio结构。
请求描述符中的几个字段值可能是动态变化的。例如,一旦bio中引用的数据块全部传送完毕,bio字段立即更新从而指向请求链表中的下一个bio。struct hd_geometry在此期间,另一个新的bio可能被加人到请求链表的尾部,所以biotail的值也可能改变。
当磁盘数据块正在传送时,请求描述符的其它几个字段的值由I/O调度程序或设备驱动程序修改。例如,nr_sectors存放整个请求还需传送的扇区数,current_nr_sectors存放当前bio结构中还需传送的扇区数。
flags中存放了很多标志,如下表中所示。到目前为止,最重要的一个标志是REQ_RW,它确定数据传送的方向。
REQ_RW 数据传送的方向:READ(0)或WRITE(1)
REQ_FAILFAST 万一出错请求申明不再重试I/O操作
REQ_SOFTBARRIER 请求相当于I/O调度程序的屏障
REQ_HARDBARRIER 请求相当于1/O调度程序和设备驱动程序的屏障—应当在旧请求与新请求之间处理该请求
REQ_CMD 包含一个标准的读或写I/O数据传送的请求
REQ_NOMERGE 不允许扩展或与其它请求合并的请求
REQ_STARTED 正处理的请求
REQ_DONTPREP 不调用请求队列中的prep_rq_fn方法预先准备把命令发选项发给硬件设备
REQ_QUEUED 请求被标记——也就是说,与该请求相关的硬件设备可以同时管理很多未完成数据的传送
REQ_PC 请求包含发送给硬件设备的直接命令
REQ_BLOCK_PC 与前一个标志功能相同,但发送的命令包含在bio结构中
REQ_SENSE 请求包含一个“sense”请求命令(SCSI和ATAPI设备使用)
REQ_FAILED 当请求中的sense或direct命令的操作与预期的不一致时设置该标志
REQ_QUIET 万一I/O操作出错请求申明不产生内核消息
REQ_SPECIAL 请求包含对硬件设备的特殊命令(例如,重设驱动器)
REQ_DRIVE_CMD 请求包含对IDE磁盘的特殊命令
REQ_DRIVE_TASK 请求包含对IDE磁盘的特殊命令
REQ_DRIVE_TASKFILE 请求包含对IDE磁盘的特殊命令
REQ_PREEMPT 请求取代位于请求队列前面的请求(仅对IDE磁盘而言)
REQ_PM_SUSPEND 请求包含一个挂起硬件设备的电源管理命令
REQ_PM_RESUME 请求包含一个唤醒硬件设备的电源管理命令
REQ_PM_SHUTDOWN 请求包含一个切断硬件设备的电源管理命令
REQ_BAR_PREFLUSH 请求包含一个要发送给磁盘控制器的“刷新队列”命令
REQ_BAR_POSTFLUSH 请求包含一个已发送给磁盘控制器的“刷新队列”命令
介绍完了这些来自ULK-3上的基础知识,我们通过一个图把前面的知识串联起来:
前面提到generic_make_request调用q->make_request_fn方法将bio请求插入请求队列q中。那么接下来的工作就交给I/O调度层了。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-48358-5.html
难道我们就可放弃原则不作为吗
还说什么别轻举妄动