乾坤合一:Linux设备驱动之块设备驱动

1. 题外话

在蜕变成蝶的一系列学习当中,我们已经掌握了大部分Linux驱动的知识,在乾坤合一的分享当中,以综合实例为主要讲解,在一个月的蜕茧成蝶的学习探索当中,觉得数据结构,指针,链表等等占据了代码的大部分框架,这些都需要我们平时多看代码,并且在相关知识点的时候需要在电脑上进行操作,这也让自己受益匪浅,笔者在这期间受到了几家IT学院的邀请录制视频,当兼职布道师。但毕竟自己还是个学生,应该潜心学习,争取更好的做一个IT的人才,所以都没有接受,这里很抱歉,并且会更加努力,好好钻研,希望和大家一起共同进步~

2. 块设备与字符设备I/O口操作异同

2.1 块设备只能以块为单位接受输入和返回输出,而字符设备则以字节为单位。大多数设备是字符设备,因为它们不需要缓冲而且不以固定块大小进行操作。

2.2 块设备对于I/O 请求有对应的缓冲区,因此它们可以选择以什么顺序进行响应,字符设备无须缓冲且被直接读写。对于存储设备而言调 读写的顺序作用巨大,因为在读写连续的扇区比分离的扇区更快。

2.3 字符设备只能被顺序读写,而块设备可以随机访问。虽然块设备可随机访问,但是对于磁盘这类机械设备而言,顺序地组织块设备的访问可以提高性能。

3. 块设备驱动结构

3.1 block_device_operations 结构体

3.2 gendisk 结构体

3.3 gendisk的操作

3.4 request 与bio 结构体

1) 请求

在Linux 块设备驱动中,使用request 结构体来表征等待进行的I/O 请求,request 结构体的主要成员包括(只用于内核块设备层):

2) 请求队列

一个块请求队列是一个块I/O 请求的队列,请求队列跟踪的块I/O 请求,它存储用于描述这个设备能够支持的请求的类型信息、它们的最大大小、多少不同的段可进入一个请求、硬件扇区大小、对齐要求等参数,其结果是:如果请求队列被配置正确了,它不会交给该设备一个不能处理的请求。

3) 块I/O

通常一个bio 对应一个I/O 请求,一个请求可以包含多个bio。

3.5  块设备驱动注册与注销

首先注册她们自己到内核,其函数原型如下

与register_blkdev()对应的注销函数是unregister_blkdev(),其原型为:

4 Linux 块设备驱动的模块加载与卸载

4.1 需要完成的工作

  • 分配、初始化请求队列,绑定请求队列和请求函数。
  • 分配、初始化gendisk,给gendisk 的maj or、fops 、queue 等成员赋值,最后添加gendisk。
  • 注册块设备驱动。

4.2 块设备驱动的模块加载函数模板 (使用bl k_a llo c_que ue )

4.3 块设备驱动的模块加载函数模板(使用bl k_ i nit_queue )

4.4 在块设备的open()函数中赋值private_data

5 块设备的I/O请求处理

5.1 使用求情队列

块设备驱动请求函数的原型为:

下面给出了一个更复杂的请求函数,它进行了3 层遍历:遍历请求队 列中的每个请求,遍历请求中的每个bio,遍历bio 中的每个段。请求函数遍历请求、bio 和段如下:

5.2 不适用请求队列

有些设备不需要使用请求队列,其函数原型如下:

在处理处理bio完成后应该使用bio_endio()函数通知处理结束,如下所示:

不管对应的I/O 处理成功与否,“制造请求”函数都应该返回0 。如果“制造请求” 函数返回一个非零值,bio 将被再次提交。下面代码所示为一个 “制造请求”函数的例子。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 1 收藏 评论

关于作者:李辉

湖南省天杰信息技术有限公司创始人之一,主要从事基站智能门禁锁、智能蓝牙锁、智慧商城等等的研发。在2015年1月完成《24小时学通Linux内核》的写作,目前其关于嵌入式Linux 驱动的写作仍在进行中。 个人主页 · 我的文章 · 2 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部