块设备驱动实战基础篇二 (继续完善170行过滤驱动代码至200行)


1.3块设备驱动关键数据结构及函数API详细剖析

经过上节四个步骤我们已经熟悉并实战了一个最基本的过滤块设备驱动的设计技巧,我们这一节先不继续实战,我们本节把上节170行代码中接触到的块设备核心数据结构和API接口剖析一下,把这部分掌握和理解一下。

 

我们把上节涉及的六个数据结构和相关API接口罗列一下:

 块设备核心数据结构

gendisk

块设备仓库

hd_struct

块设备分区

block_device

文件系统层使用的块设备描述符

request_queue

仓库的关卡(请求队列)

request

包含多个bio的大请求

bio

单个请求

块设备核心API接口

register_blkdev

注册并申请门牌号

alloc_disk

申请仓库

blk_alloc_queue

申请仓库的关卡

blk_queue_make_request

注册仓库的加工处理函数

add_disk

将申请的仓库注册到内核中,成为合法仓库

 

 

 

结合上节块设备在Linux中的总体结构图来看,我们再贴一下这个图,根据这个图我们将请求从文件系统层构建出bio开始,直到进入到请求处理函数,分析一下其过程,这个过程会扩展描述到核心数据结构中的几个关键字段,大家先试着熟悉,然后我们会给出核心数据结构的嵌套关系图,让大家更清楚的认识一下各个核心数据结构之间的关系,最后我们会详细剖析各个数据结构和API接口功能。

 

 

上层文件系统发来I/O请求时,我们在块设备驱动的请求处理函数make_request上接收到的是bio,每个bio结构中都包含了一个bio_vec数组。bio_vec是用于记录一段连续内存空间位置信息的数据结构,包括描述这段内存连续空间的页指针描述符bv_page,数据长度bv_len,数据在一个页中的开始位置bv_offset。如此分析我们知道bio请求包含了一个bio_vec数组,意味着包含了一组内存连续空间。

 

接下来文件系统层调用通用块层的generic_make_request函数,将请求插入到仓库的关卡即请求队列上request_queue,如果队列没有使用,则继续调用到我们注册的请求处理函数make_request上。

 

请求队列request_queue中的每一个元素是一个请求集合request,request包含了多个bio请求,同时多个request通过链表链接在一起,链表头在request_queue上;同样request中的多个bio也通过链表链接在一起。

 

磁盘描述符gendisk通过指向该磁盘的请求队列的指针queue与其请求队列关联起来。内核用结构block_device代表一个块设备对象,它是文件系统层使用的数据结构,如:整个硬盘或特定分区都是一个块设备对象。如果该结构代表一个分区,则其成员bd_part指向设备的分区结构;如果该结构代表设备,则其成员bd_disk指向设备的通用硬盘结构gendisk。

 

       根据上面的描述,我们把数据结构关系画一下,如下,大家可以更清楚的看一下各个结构之间的关系,也更加能够从整体上把握IO请求在操作系统内核中的描述和处理。

 

 

 

 

根据上面这个图,让我们可以继续总结一下,充分把握好它们的结构关系。块设备会有一个仓库描述gendisk,如果仓库有分区,则分区由hd_struct描述,同时文件系统会对仓库及分区都用一个独立的block_device进行描述;文件系统产生bio请求,多个bio会组装成一个request,多个request会组装到request_queue请求队列上。

 

好了,至此相信大家能够很牢固的记住各结构之间的关系了,并且能够根据上图从整体上把握好应用层数据读写请求在操作系统内核中的处理关系,下面我们详细剖析一下各个数据结构及API的功能,大家可以作为一个参考,再后面实战时可以继续回来进行查阅学习。

 

 

   block_device关键成员剖析

类型

字段

说明

dev_t

bd_dev

块设备的主设备号和次设备号

struct inode*

bd_inode

指向bdev文件系统中块设备对应的文件索引节点的指针

int

bd_openers

计数器,统计块设备已经被打开了多少次

struct mutex

bd_mutex

打开或关闭的互斥量

struct list_head

bd_inodes

已打开的块设备文件的索引节点链表的首部

void*

bd_holders

块设备描述符的当前所有者

struct block_device*

bd_contains

如果块设备是一个分区,则指向整个磁盘的块设备描述符;否则,指向该块设备描述符

unsigned

bd_block_size

块大小

struct hd_struct*

bd_part

指向分区描述符的指针(如果该块设备不是一个分区,则为NULL)

unsigned

bd_part_count

计数器,统计包含在块设备中的分区已经被打开了多少次

struct gendisk*

bd_disk

指向块设备中基本磁盘的gendisk结构的指针

struct list_head

bd_list

用于块设备描述符链表的指针

unsigned long

bd_private

指向块设备持有者的私有数据的指针

 

   hd_struct关键成员剖析

类型

字段

说明

sector_t

start_sect

磁盘中分区的起始扇区

sector_t

nr_sects

分区的长度(总共的扇区数)

int

policy

如果分区是只读的,则置为1;否则为0

int

partno

磁盘中分区的相对索引

 

   gendisk关键成员剖析

类型

字段

说明

int

major

磁盘主设备号, 每个块设备都有唯一的主设备号,在这个块设备上建立的分区都使用这个相同的主设备号。具有相同主设备号的设备,使用相同的驱动程序。

int

first_minor

与磁盘关联的第一个次设备号。在某一个设备上首先

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值