I.MX6U嵌入式Linux Platform设备驱动开发---块设备驱动

块设备驱动是Linux 三大驱动类型之一。

1、块设备的概念

块设备是针对存储设备的,比如 SD 卡、EMMC、NAND Flash、Nor Flash、SPI Flash、机械硬盘、固态硬盘等。因此块设备驱动其实就是这些存储设备驱动。

块设备驱动相比字符设备驱动的主要区别如下:

块设备字符设备
以块为单位进行读写访问以字节为单位进行数据传输
使用缓冲区来暂存数据,可以随机访问顺序的数据流设备,不需要缓冲区,实时访问

2、块设备驱动框架

2.1、block_device结构体

linux 内核使用 block_device 表示块设备 ,block_device 为 一 个结构体 , 定义在include/linux/fs.h 文件中。重点成员变量:struct gendisk *bd_disk;

内核使用 block_device 来表示一个具体的块设备对象,比如一个硬盘或者分区,如果是硬盘的话 bd_disk 就指向通用磁盘结构 gendisk。

与字符设备驱动一样,需要向内核注册新的块设备、注销块设备。

int register_blkdev(unsigned int  major, const char  *name)
void unregister_blkdev(unsigned int major, const char  *name)

2.2、gendisk结构体

linux 内核使用 结构体gendisk 来描述一个磁盘设备,定义在 include/linux/genhd.h中,

1 struct gendisk {
5 		int major; /* 磁盘设备的主设备号 */
6 		int first_minor; /* 磁盘的第一个次设备号 */
7 		int minors;//minors 为磁盘的次设备号数量,也就是磁盘的分区数量,这些分区的主设备号一样,次设备号不同
10 		char disk_name[DISK_NAME_LEN]; /* name of major driver */
11 		char *(*devnode)(struct gendisk *gd, umode_t *mode);
12
13 		unsigned int events; /* supported events */
14 		unsigned int async_events; /* async events, subset of all */

21 		struct disk_part_tbl  __rcu *part_tbl;//为磁盘对应的分区表,disk_part_tbl 的核心是一个 hd_struct 结构体指针数组,此数组每一项都对应一个分区信息
22 		struct hd_struct part0;
23
24 		const struct block_device_operations *fops;//fops 为块设备操作集,和字符设备操作集 file_operations 一样,是块设备驱动中的重点!
25 		struct request_queue *queue;//queue 为磁盘对应的请求队列,所以针对该磁盘设备的请求都放到此队列中,驱动程序需要处理此队列中的所有请求。
26 		void *private_data;
27
28 		int flags;
29 		struct device *driverfs_dev; // FIXME: remove
30 		struct kobject *slave_dir;
31
32 		struct timer_rand_state *random;
33 		atomic_t sync_io; /* RAID */
34 		struct disk_events *ev;
35 #ifdef 	CONFIG_BLK_DEV_INTEGRITY
36 		struct blk_integrity *integrity;
37 #endif
38 		int node_id;

编写块的设备驱动的时候需要分配并初始化一个 gendisk,linux 内核提供了一组 gendisk 操作函数,

struct gendisk *alloc_disk(int minors);//申请 gendisk
void del_gendisk(struct gendisk *gp);//删除 gendisk
void add_disk(struct gendisk *disk);//将 gendisk 添加到内核
void set_capacity(struct gendisk *disk, sector_t size);//设置 gendisk 容量

//内核会通过 get_disk 和 put_disk 这两个函数来调整 gendisk 的引用计数
truct kobject *get_disk(struct gendisk *disk)//增加 gendisk 的引用计数
void put_disk(struct gendisk *disk)//减少 gendisk 的引用计数

2.3、 block_device_operations 结构体

块设备的操作集。和字符设备的 file_operations操作集基本类似。

2.4、 块设备I/O请求过程

在 block_device_operations 结构体中并没有找到 read 和 write 这样的读写函数,那么块设备是怎么从物理块设备中读写数据?这里就引出了块设备驱动中非常重要的 request_queue、request 和 bio。

内核将对块设备的读写都发送到请求队列 request_queue 中,request_queue 中是大量的request(请求结构体),而 request 又包含了 bio,bio 保存了读写相关数据,比如从块设备的哪个地址开始读取、读取的数据长度,读取到哪里,如果是写的话还包括要写入的数据等。

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值