我们大概来猜一下它的框架是怎么样的
应用程序 open read write一个普通的文件“1.txt”
1.txt最终肯定要操作硬件啊,比如硬盘啊 flash等等
然后中间是块设备驱动程序,对普通文件的读写肯定要转换成对块设备文件的读写,你要读写哪一个扇区,那谁来把文件的读写来转换成对扇区的读写呢???
中间就引入了文件系统
ll_rw_block是通用的入口 这ll_rw_block会把读写放入队列 调用队列的处理函数,队列的处理函数会优化啊 调顺序啊
我们可以看看ll_rw_block
文件系统把对文件的读写,转换为对块设备 扇区的读写最终就会调用这个底层的函数ll_rw_block 意思就是底层的读写块
第一个参数rw表示是读还是写,数据传输3要素源 目的 长度放到哪里呢 放到buffer_head里面 是个数组,但是数组里面有多少项呢 ,用nr来表示
我们来看看这个函数做了什么事情
先做了一个循环,我们只抓重要的一点提交 submit_bh 提交buffer_head
先分析到这里
大家看这个文件也挺有意思的,它处于文件系统的,看一下内核目录,内核文件目录下面有各种具体的文件系统,所谓文件系统就是文件的组织格式,它是一种纯软件的概念
这些.c应该是通用的文件,我们这个ll_rw_block位于buffer.c里面,它是一个通用的文件,并且文件名很有意思是buffer.c 之前我们不是说对块设备的读写并不会立刻执行而是把它放到一个队列里面,先把它缓存起来。
我们来看看提交buffer_head做了什么事情
第一行 struct bio *bio 使用bh来构造bio bio是什么意思呢 是block input/output 块设备输入输出 然后提交bio 接着往里面看,看提交bio又做了什么事情
generic_make_request 通用的构造请求 使用bio来构造请求
看看这个函数
又调用__generic_make_request(bio); 这个函数,进入这个函数
bdev_get_queue获得队列
这个q是什么东西
是request_queue 请求队列
然后这里就是调用队列里的一个函数
看名字是构造请求的函数,我们有默认的函数,我们搜索看这个变量在哪里被设置
默认函数是__make_request 我们来看看这个函数做了什么事情
elv_merge合并
代码是先尝试合并
elv是电梯调度算法的意思
什么叫电梯调度算法呢
我们回过头来看一看
我们之前说硬盘优化怎么做呢,我先读
读完之后再来写,我一次先上,然后在下,我一次运输尽可能传输更多的人
以电梯调度算法合并请求
如果能何必就最好了,如果不能合并就使用bio构造一个请求,然后把请求放入队列
这就是我们块设备驱动程序的框架
那我们怎么写块设备驱动程序呢
分配/设置队列 request_queue_t 这个队列干什么用的 这个队列只是给我们提供了读写的能力而已 还要提供读写能力 还需要提供属性:如容量等
1.分配一个gendisk alloc_disk
2.设置
2.1 分配/设置队列 request_queue_t //提供读写能力
blk_init_queue
2.2 设置gendisk其他信息 提供属性
3 注册 add_disk