第6章 设备驱动程序(3)

2024-06-19 16:20
文章标签 设备 驱动程序

本文主要是介绍第6章 设备驱动程序(3),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

6.5 块设备操作

6.5.1 块设备的表示

6.5.2 数据结构

6.5.3 向系统添加磁盘和分区

6.5.4 打开块设备文件


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

6.5 块设备操作

特点:

        随机访问任意位置。

        固定块大小的传输。

        块设备在内存进行缓存。

扇区(sector):

        最小寻址单位。

        固定的硬件单位,常数,软件不可修改。

        常见大小:512B。

块(block):

        长度:扇区的整数倍。软件可修改。

        用于在内核和设备之间传输,受内存页限制

        常见大小:512B,1024B,2048B,4096B。最大不超过页大小。

一个文件系统内有大块,也有小块。

        优点:处理不同大小文件时分别优化性能。

块设备层工作有:

        1. 寻址块设备。

        2. 预读算法,预读块设备到内存。

6.5.1 块设备的表示

块设备的请求队列管理,包括:

        1. 重排读写块请求。

        2. 在内存中缓存读写的内容。

struct         bdev_inode {         //关联块设备与inode

        struct block_device         bdev;                 块设备

        struct inode                     vfs_inode;         块设备的inode

};

struct block_device *bdget(dev_t dev)

        根据设备号找到对应块设备。

        dev_t -> inode -> struct bdev_inode -> struct block_device

每个块设备有一个请求队列。包含了:

        读写请求

        IO调度器 :用于重排请求。

        特征数据:扇区,块长度。

上图中通用硬盘,用struct gendisk表示。

void add_disk(struct gendisk *disk);

        将通用硬盘添加到内核。

对块设备的读写请求不会立即执行,而是协同汇总一起发给设备。

所以块设备文件的file_operations没有实现读写函数。

6.5.2 数据结构

1. 块设备

一个flash或硬盘中有多个分区。

        如/dev/mtblockN, 或/dev/sdaN

struct gendisk:表示一个flash或硬盘。

struct block_device:每个分区有一个该结构的实例。

struct block_device {

        dev_t                    bd_dev;                 //设备号

        int                         bd_openers;         //打开该块设备的次数

        struct inode         *bd_inode;              //bdev伪文件系统中,该块设备的inode

        struct super_block        *bd_super;    //设备挂载的文件系统

        struct mutex                   bd_mutex;

        struct list_head              bd_inodes;

        struct block_device       *bd_contains;

        unsigned                        bd_block_size;

        struct hd_struct              *bd_part;         //该块设备上的某个分区

        unsigned                        bd_part_count;         //引用分区的次数

        int                                   bd_invalidated;

        struct gendisk                *bd_disk;         //块设备在通用磁盘层的表示。

        struct request_queue     *bd_queue;

        struct list_head               bd_list;         //连接系统所有可用的block_device

        unsigned long                 bd_private;         //私有数据

};

bd_invalidated:

        若为1,则该分区在内核中信息无效,因为磁盘分区已改变。

blkdev_open:

        打开块设备并独占使用。

2. 通用硬盘和分区

struct         gendisk {         //驱动层,表示一个已分区的硬盘。

        int                 major;                 //主设备号。

        int                 first_minor;         //第一从设备号。

        int                 minors;                 //从设备号总数。

                //每个分区有各自的从设备号。

        char                 disk_name[DISK_NAME_LEN];         // 驱动程序的名字

        char                 *(*devnode)(struct gendisk *gd, umode_t *mode);

                //用于生成设备节点。创建设备文件时调用。

        unsigned short             events;                     //磁盘事件

        unsigned int                 async_events;         //异步的磁盘事件

        struct disk_part_tbl      *part_tbl;                  //分区表

        struct hd_struct            part0;

        struct block_device_operations         *fops;

        struct request_queue                         *queue;         //管理IO请求

        void                      *private_data;         //磁盘的私有数据

        int                         flags;                       //磁盘的特性或状态

        struct kobject        *slave_dir;

};

成员part0:

        不对应于磁盘上的实际分区,而是代表整个磁盘。允许以分区的方式对整个磁盘操作。

        起始扇区:

                part0的起始扇区为是 0,表示磁盘的第一个扇区。

        大小:

                part0 的大小等于整个磁盘的大小。

        操作:

                对part0的操作实际上是对整个磁盘的操作(如格式化)

每个分区都有一个struct hd_struct实例。

struct hd_struct {

        sector_t         start_sect;         //分区在磁盘的起始扇区。

        sector_t         nr_sects;         //该分配的总扇区数。

        struct kobject         *holder_dir;

};

struct gendisk *alloc_disk(int minors);

        参数minors:从设备数目。

        作用:分配struct gendisk,包括每个分区的hd_struct指针。

void del_gendisk(struct gendisk *gp);

3. 几个结构体的联系

一个磁盘(struct gendisk)有多个分区。

        其中每个分区都有一个:

                struct         block_device(打开该分区设备文件时创建)

                struct         hd_struct

struct gendisk:一个磁盘。

struct hd_struct:磁盘中一个分区。

struct block_device:VFS层,打开一个分区的设备文件时创建该结构体实例。

struct hd_struct的kobject->parent指向struct gendisk的kobject。

4. 块设备操作

//不由VFS调用,而是被def_blk_fops调用

struct         block_device_operations {

        int         (*open) (struct block_device *, fmode_t);

        void      (*release) (struct gendisk *, fmode_t);

        int         (*media_changed) (struct gendisk *);

                //检查存储介质是否改变(磁盘是否被移除了)

        int         (*revalidate_disk) (struct gendisk *);

                //替换一个新存储介质时使用。

};

5. 请求队列

请求队列:包含对一个块设备的读写请求。

struct         gendisk {

        struct request_queue         *queue;

}

struct         block_device {

        struct request_queue         *bd_queue;

}

struct         request_queue {

        struct list_head         queue_head;

                //连接块设备的IO请求(struct request),内核会重排链表以提高性能。

        struct elevator_queue         *elevator;

        request_fn_proc                 *request_fn;

                //向队列添加新读写IO请求。

                //该函数需要驱动各自实现。

        make_request_fn                 *make_request_fn;

                //创建新请求。

        softirq_done_fn                   *softirq_done_fn;

                //异步处理IO请求时,用于通知请求已处理完毕。

        struct request_list                 rq;                       //request实例的缓存

        unsigned long                      nr_requests         //队列可管理的请求最大数目

        unsigned long                      queue_flags;        //队列标志

}

struct request_queue *blk_init_queue_node(request_fn_proc *rfn,

spinlock_t *lock, int node_id)

        作用:生成一个标准的请求队列。

6.5.3 向系统添加磁盘和分区

1. 添加分区

struct hd_struct    *add_partition(struct gendisk   *disk,    int partno,

sector_t   start,    sector_t    len,    int    flags, ,)

        作用:向通用硬盘(struct gendisk)添加一个新分区。

        内容:

                1. 分配struct hd_struct实例。并初始化分区信息。

                2. 设置p->kobj,然后kobject_add();

2. 添加硬盘

void   add_disk(struct gendisk    *disk):

        作用:向系统添加通用硬盘。

6.5.4 打开块设备文件

创建块设备的设备文件时(mknod),调用init_special_inode函数。

void    init_special_inode(struct inode    *inode,    umode_t    mode,    dev_t   rdev)

{

        inode->i_mode    =    mode;

        if (S_ISBLK(mode)) {

                inode->i_fop    =    &def_blk_fops;

        }

}

struct file_operations         def_blk_fops     =    {

        .open     =     blkdev_open,

};

所以打开块设备的设备文件时:

        VFS将调用blkdev_open(struct inode * inode, struct file * filp)

这篇关于第6章 设备驱动程序(3)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075532

相关文章

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑燃料电池和电解槽虚拟惯量支撑的电力系统优化调度方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源程序擅长文章解读,论文与完整源程序,等方面的知识,电网论文源程序关注python

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

海鲜加工污水处理设备处理效果高

诸城市鑫淼环保小编带大家了解一下海鲜加工污水处理设备处理效果高   海鲜加工污水处理设备通常采用物理、化学和生物处理相结合的方法,对废水中的污染物进行高xiao去除。设备设计紧凑,占地面积小,操作简便,适用于不同规模的海鲜加工厂。   设备特点   高xiao性:采用先进的处理工艺和技术,确保废水处理效果稳定可靠。   占地面积小:设备设计紧凑,占地面积小,适合在有限的空间内安装。

集运系统需要与哪些硬件设备集成?

随着电商和跨境贸易的不断发展,集运服务越来越受到海外用户的青睐。集运系统作为一种高效的跨境物流管理工具,可以协调各个环节之间的物流流程,提高物流效率和管理水平,被越来越多的集运企业采用。而集运系统作为集运服务的重要组成部分,也需要配套相应的硬件设备才能更好地支持跨境集运业务。下面就来介绍一下集运系统需要哪些硬件设备支持呢? 1.PDA:是一种便携式电子设备,可以轻松地进行数据采集和处理,具有移

3.门锁_STM32_矩阵按键设备实现

概述 需求来源: 门锁肯定是要输入密码,这个门锁提供了两个输入密码的方式:一个是蓝牙输入,一个是按键输入。对于按键输入,采用矩阵按键来实现。矩阵按键是为了模拟触摸屏的按键输入,后续如果项目结束前还有时间就更新为触摸屏按键输入。 矩阵按键开发整体思路: 由于矩阵按键就是GPIO的控制,所以不进行芯片和设备的分层编写,控制写在同一个文件中,最终向应用层提供一个接口。 代码层级关系:

C#通过ACE OLEDB驱动程序访问 Access和 Excel

ACE 代表 Access Connectivity Engine。它是 Microsoft 提供的一组组件,用于访问和操作 Microsoft Access 数据库以及其他类似的文件格式,如 Excel 工作簿。ACE 主要包括以下几部分: ACE OLEDB 驱动程序:用于通过 OLE DB 提供程序访问 Access 数据库和 Excel 文件。例如,Microsoft.ACE.OLED

Anroid BLE蓝牙(手机分别作为中心设备和外围设备)

蓝牙是一种短距的无线通讯技术,可实现固定设备、移动设备之间的数据交换。一般将蓝牙3.0之前的BR/EDR蓝牙称为传统蓝牙,而将蓝牙4.0规范下的LE蓝牙称为低功耗蓝牙。  BLE蓝牙模块主要应用领域     1、移动扩展设备     2、汽车电子设备     3、健康医疗用品:心跳带、血压计等     4、定位应用:室内定位、井下定位等     5、近距离数据采集:无线

RS在不同设备间同步文件

参考: 1. Resilio(BtSync)搭建 2. 使用Resilio Sync共享文件【附操作指南】 4. Linux 下挂载新硬盘方法 5. Partition 1 does not start on physical sector boundary. 6. Ubuntu 16.04添加开机启动脚本的方法 7. Ubuntu 16.04以普通用户身份开机启动 8. Ubunt