块设备驱动框架


块设备和字符设备的差异
(1)块和字符是两种不同的访问设备的策略
(2)同一个设备可以同时支持块和字符两种访问策略
(3)设备本身的物理特性决定了哪一种访问策略更适合
(4)块设备本身驱动层支持缓冲区,而字符设备驱动层没有缓冲
(5)块设备驱动最适合存储设备

块设备驱动的特点
(1)字符设备只能顺序访问(如串口发送数据顺序),而块设备可以随机访问(不连续块访问)
(2)传统的机械式块设备(如硬盘、DVD)虽然可以随机访问,但是连续访问效率更高,因此块设备驱动中有排序逻辑将用户的随机访问重新调整成尽量连续访问以提升效率
(3)Nand、SD卡等随机访问效率等同于顺序访问

块设备相关的几个单位
(1)扇区(Sector),概念来自于早期磁盘,在硬盘、DVD中还有用,在Nand/SD中已经没意义了,扇区是块设备本身的特性,大小一般为512的整数倍,因为历史原因很多时候都向前兼容定义为512.
(2)块(block),概念来自于文件系统,是内核对文件系统数据处理的基本单位,大小为若干个扇区,常见有512B、1KB、4KB等
(3)段(Section),概念来自于内核,是内核的内存管理中一个页或者部分页,由若干个连续为块组成。
(4)页(Page),概念来自于内核,是内核内存映射管理的基本单位。linux内核的页式内存映射名称来源于此。
总结:块设备驱动对下以Sector为单位管理块设备,对上以Block为单位和文件系统交互。
注意:块设备驱动和字符设备驱动不同,应用层对块设备驱动的访问一般不是直接操作设备文件(/dev/block/xxx,或者/dev/sdax),而是通过文件系统来简洁操作。(思考裸机阶段时刷机烧录SD卡时说过的对SD卡的2种访问:文件系统下访问和扇区级访问)

块设备驱动框图
(1)VFS
(2)通用块层
(3)IO调度层(电梯算法)
(4)块设备驱动层(真正硬件操作部分)

重点结构体
(1)struct request 对设备的每一次操作(譬如读或者写一个扇区)
(2)struct request_queue request队列
(3)struct bio 通用块层用bio来管理一个请求
(4)struct gendisk 表示一个磁盘设备或一个分区

块设备驱动案例演示
(1)驱动简单介绍
(2)编译
(3)模块安装
(4)查看信息 cat /proc/devices cat /proc/partitions ls /dev/ lsmod
(5)挂载测试

块设备驱动简单分析
(1)如何证明块设备驱动真的工作了: 格式化、挂载
格式化:mkfs.ext2 /dev/my_ramblock
挂载: mount -t ext2 /dev/my_ramblcok   /tmp
(2)注意各种打印信息
(3)体会块设备驱动的整体工作框架


源码分析
(1)register_blkdev(kernel/block/genhd.c),内核提供的注册块设备驱动的注册接口,在块设备驱动框架中的地位,等同于register_chrdev在字符设备驱动框架中的地位。
(2)blk_init_queue 用来实例化产生一个等待队列,将来应用层对本块设备所做的所有的读写操作,都会生成一个request然后被加到这个等待队列中来。
(3)blk_init_queue函数接收2个参数,第一个是等待队列的回调函数,这个函数是驱动提供的用来处理等待队列中的request的函数(IO调度层通过电梯算法从等待队列中取出一个request,就会调用这个回调函数来处理这个请求),第二个参数是一个自旋锁,这个自旋锁是要求我们驱动提供给等待队列去使用的。
(4)blk_fetch_request函数是IO调度层提供的接口,作用是从request_queue中(按照电梯算法)取出一个(算法认为当前最应该去被执行的一个请求,是被算法排序、合并后的)请求,取出的请求其实就是当前硬件(块设备)最应该去执行的那个读写操作。

原文地址:https://www.cnblogs.com/zhangshuaifeng/p/10668143.html