在上一篇文章中《linux块设备总结(四) 块设备数据组织》[link][https://blog.csdn.net/weixin_37867857/article/details/88856550]我们看到了数组的组织结构,下面对于上一章中做一个总结,同时也会引申一个重要的数据结构struct gen_hd,同时也作为一个承上启下的作用,为以后我们介绍块设备的重要的函数做一一个承接。
在上一篇文章中我们知道块设备中重要的数据结构包括如下:
struct block_device
struct hd_struct
struct gen_disk
struct request_queue
struct request;struct bio
其中各个数据结构联系如下:
从以上图片中,我们看到,对于各个数据结构都有联系的主要数据结构为struct gen_disk
(通用磁盘结构)。看来这个数据结构相当重要,即使不是相当重要也是相当于中学作文里面的承上启下的作用。没错,这个数据结构相当重要也起到了承上启下的作用。
struct gen_disk
的作用主要如下:
1.连接块设备文件,使应用层快速定位到我们要操作的磁盘上。
2.通过对于快设备文件的组织结构,来进行磁盘的IO操作。(注意:磁盘的IO操作不是文件的IO操作。文件IO操作可能触发磁盘的IO操作,但是磁盘的IO操作肯定是文件的IO操作触发的。)
gen_disk在各个阶段的作用
我们在上文提到了块设备文件的作用,下图是关于块设备的组织结构的另外一种表示方法和方式。
读者乍一看怎么和上一章中的块设备数据的组织结构有很大不同啊?难道上一章中有错误,或者本章故意简化。实际上上一章中的关于块设备的数据结构没有强调各个阶段
,实际上本章主要是块设备文件在各个阶段的作用的。以下是gen_disk在各个阶段的不同作用:
1.在打开阶段根据dev_t找到相应的block_device结构,并且找到gen_disk。
2.读取阶段直接在块设备的gen_disk执行相应的IO操作。
gen_disk链接块设备文件
如下图,是gen_disk在生成的时候的代码组织结构:
以上组织结构是相当复杂的,我们暂且不讨论其具体的组织结构(比如怎么获取的?)我们来介绍一下它是如何获取的。
1.执行bdev_open过程中根据各个磁盘的节点(dev_t设备号)来获取block_device结构;
2.根据分区的block_device结构来获取gen_disk结构。
gen_disk的IO链接属性
gen_disk作用就是处理来自上层对所有块设备发出的io操作。例如,上层文件系统对磁盘上某个文件的读写操作都会转换成相应的io操作然后交给我们的通用块层进行处理。
如果具体展开gen_disk和request_queue结构,我们会发现如下结构:
struct request_queue *queue;:
struct list_head queue_head;
struct request *last_merge;
request_fn_proc *request_fn;
make_request_fn *make_request_fn;
prep_rq_fn *prep_rq_fn;
unplug_fn *unplug_fn;
merge_bvec_fn *merge_bvec_fn;
prepare_flush_fn *prepare_flush_fn;
softirq_done_fn *softirq_done_fn;
rq_timed_out_fn *rq_timed_out_fn;
dma_drain_needed_fn *dma_drain_needed;
lld_busy_fn *lld_busy_fn;
我们看到gen_disk指向的queue结构不止有请求队列还有请求队列的操作以及请求队列的排序等等。