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

news2024/11/17 16:15:51

目录

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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1838806.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探究 IP 地址被网站封禁的原因

在我们登录各种网站、APP浏览时,可能会遇到 IP 地址被某些网站封禁的情况。很多人奇怪这是为什么呢? 首先,违反网站的使用规则是比较常见的原因之一。比如,频繁发送垃圾邮件、恶意评论、进行网络攻击或试图破解网站的安全机制等不…

邻氯苯甲酰氯在医药、农药等领域应用广泛 市场需求稳定且有增长趋势

邻氯苯甲酰氯在医药、农药等领域应用广泛 市场需求稳定且有增长趋势 邻氯苯甲酰氯又称为2-氯苯甲酰氯、氯化邻氯苯甲酰,化学式为C7H4Cl2O,是一种化学物质,外观为黄色液体,不溶于水,溶于醇、醚、丙酮,有强烈…

调度算法-进程调度算法

发⽣ CPU 调度通常有以下情况: 1. 当进程从运⾏状态转到等待状态;2. 当进程从运⾏状态转到就绪状态;3. 当进程从等待状态转到就绪状态;4. 当进程从运⾏状态转到终⽌状态 常⻅的调度算法: 先来先服务调度算法最短作业…

@pytest.fixture与@pytest.mark.parametrize结合实现参数化

背景:测试数据既要在fixture方法中使用,同时也在测试用例中使用 使用方法:在使用parametrize的时候添加"indirectTrue"参数。pytest可以实现将参数传到fixture方法中,也可以在当前测试用例中使用。 原理:参…

硕思闪客精灵_2024最新版下载-闪客精灵软件下载_闪客精灵应用软件

​不同领域的应用证明了能够解析Flash动画片中的视频文件并以*.fla格式进行导出。人所共知的是支持预览和播放所选的Flash动画片或元素。我们都知道除了将静态文字恢复为文本外,硕思闪客精灵提供了将它转换为矢量图的功能。相信大家都认同闪客精灵专业版的优势&…

【YOLOv10改进[注意力]】添加注意力CascadedGroupAttention(2023) + 含全部代码和详细修改方式 + 手撕结构图 + 全网首发

本文将进行使用注意力CascadedGroupAttention的实践,助力YOLOv10目标检测效果的实践,文中含全部代码、详细修改方式以及手撕结构图。助您轻松理解改进的方法。 改进前和改进后的参数对比: 目录 一 CascadedGroupAttention 二 使用注意力CascadedGroupAttention 1 整体…

智慧校园软件开发:为学校量身定制的技术解决方案

为了满足智慧校园的需求,一套全面的软件解决方案被设计出来,旨在优化学校管理和提升教学质量。首先,通过实施统一的认证门户,结合OAuth2和SSO技术,确保不同用户群体能便捷且安全地访问所需资源。 教务管理系统被构建成…

【电源开发】输出电压纹波

输出电压纹波是什么 电压纹波指的是直流输出电压中一个交流部分 减小输出电压纹波的方法 调整输出端的电容值 提高开关电源的工作频率

项目二 OpenStack快速入门

任务一 熟悉OpenStack图形界面操作 1.1 Horizon项目 •各OpenStack服务的图形界面都是由Horizon提供的。 •Horizon提供基于Web的模块化用户界面。 •Horizon为云管理员提供一个整体的视图。 •Horizon为终端用户提供一个自主服务的门户。 •Horizon由云管理员进行管理…

码云建仓库

1.新建仓库 码云地址 打开 码云地址 ,点击“”,新建仓库,添加仓库内容 ,创建。 小提示:如果本地已有项目,就不要选初始化,设置模板,容易冲突。 2. 进入当前仓库页 小提示&#x…

Internet Download Manager(IDM下载器) v6.41官网版下载-IDM软件最新版下载附加详细安装步骤

根据大数据结果显示此软件具有动态档案分割、多重下载点技术,而且它会重复使用现有的联机,而不需再重新联机登入一遍。也就是说强大的下载引擎:强大的下载引擎使用独特的算法以最快的方式接收互联网数据,IDM由于其创新的动态文件分…

同三维高清大屏多功能一体机简介——高清多能数字矩阵

产品简介 同三维高清多能数字矩阵(硬件集软件于一体)是依据当前高清视频正广泛应用于各类项目工程的整体形势而专门研发的、特点显著、优势诸多、极具创新性的专业级一体化监控产品。高清多能数字矩阵采用WINDOWS操作系统,基于高性能配置的刀…

离线安装zabbix-agent,自制yum源方式安装

文章目录 1,机器准备大致思路 2,在机器A上操作2.1 执行完后会在/etc/yum.repos.d/下面自动生成yum文件(zabbix.repo)2.2 将官方源改为国内源2.3 修改zabbix.repo文件的[zabbix-frontend]的参数项2.4 清除缓存即可2.5 下载所需zabb…

【MAVEN学习 | 第1篇】Maven介绍与安装

文章目录 前言 一. Maven主要作用1.1 依赖管理1.2 项目构建 二. Maven安装和配置2.1 安装2.2 配置环境变量2.3 命令测试2.4 配置文件(1)依赖本地缓存位置(本地仓库位置)(2)配置国内阿里镜像(3&a…

【Pandas驯化-09】一文搞懂Pandas中字符串用法extract、zfill、isdigit

【Pandas驯化-09】一文搞懂Pandas中字符串用法extract、zfill、isdigit 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容…

tiaoshixitong

data_interval : 当是ubus 时 重新赋值为 3;当是ws 时 重新赋值为 20; 1. 如何理解data_tik ? 在函数can_packet_check_timer 定时can发送函数里面,data_tik 作为倒计时时间,当倒计时间到,则发送。…

05 部署YUM软件仓库

5.1部署YUM软件仓库 5.1.1准备网络安装源 YUM软件仓库通常借助于HTTP或FTP协议来发布,这样可以面向网络中的所有客户机提供软件源服务。 1.准备软件仓库目录 在Center 7 系统的安装光盘中,已针对软件目录Packages建立好repodata数据,因此…

【Unity】实现分屏开发

前言: 最近有个项目二期需要做分屏开发,今天恰好研究一下为后续的项目做个准备。 原理 整体的实现还是蛮简单的,主要是通过camera的一个targetDisplay属性进行设置 可以看到unity支持最多八个分屏 实现 场景搭建 ,这里直接使…

ubuntu18.0.4安装gradio踩坑记

Collecting pandas (from gradio) Downloading http://mirrors.cloud.aliyuncs.com/pypi/packages/c3/e2/00cacecafbab071c787019f00ad84ca3185952f6bb9bca9550ed83870d4d/pandas-1.1.5-cp36-cp36m-manylinux1_x86_64.whl (9.5MB) 100% |████████████████…

智警杯数据库学习(1)

CentOS中安装MySQL数据库 检测系统是否自带安装 MySQL 首先检查是否自带mysql rpm -qa | grep mysql 如果有删除 rpm -e mysq 未安装,开始安装 进入software目录,解压安装包mysql5.7.25 cd /root/software tar -xvf mysql-5.7.25-1.el7.x86_64.rp…