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

目录

6.5 块设备操作

6.5.5 请求结构

6.5.6 BIO

6.5.7 提交请求

6.5.8 I/O调度

6.5.9 ioctl实现


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

6.5 块设备操作

6.5.5 请求结构

struct         request {         //放在请求队列上,请求完成放到donelist链表上。

        struct request_queue         *q;

        struct list_head                  queuelist;            //用于挂载到请求队列中。

        struct gendisk                    *rq_disk;

        struct hd_struct                 *part;

        sector_t                             sector;                 //请求的起始扇区。

        unsigned long                   nr_sectors;          //请求包含的的扇区数。

        unsigned int                     current_nr_sectors;

        struct bio                         *bio;                         //表示底层的I/O 请求。

        struct bio                         *biotail;                   //一个请求可包含多个bio,指向最后一个bio。

        void                                 *elevator_private;         //IO调度器设置。

        void                                 *elevator_private2;

        unsigned short                         nr_phys_segments;        //请求涉及连续物理区域数。

        unsigned short                         nr_hw_segments;           //重排序的请求中连续物理区域数。

        enum rq_cmd_type_bits         cmd_type;                        //如:REQ_TYPE_FS。

        unsigned int                        cmd_flags;                          //如:_REQ_RW表示数据传输方向。

        unsigned int                        cmd_len;

}

BIO:用于内核和设备间传输数据。下节讲。

struct request在更高层次表示块设备的整体I/O请求,包含多个struct bio

6.5.6 BIO

bio:描述单个IO读写请求。

struct         bio {

        struct bio                         *bi_next;

        struct block_device         *bi_bdev;         // 对应块设备。

        sector_t                           bi_sector;        // 请求传输的开始扇区号。

        unsigned int                    bi_size;           // 请求数据的长度。

        unsigned short               bi_vcnt;           // bi_io_vec数组元素个数,即数据缓冲区数量。

        unsigned short              bi_idx;              // 作为数组bi_io_vec的索引。

        struct bio_vec               *bi_io_vec;

}

struct         bio_vec {

        struct page          *bv_page;         // 缓冲区所在页。

        unsigned int         bv_len;             // 缓冲区长度。

        unsigned int         bv_offset;         // 缓存区在页内的偏移。

};

6.5.7 提交请求

内核将IO请求提交给设备,步骤:

        1. 创建一个bio以描述请求 ,并嵌入到request中,放到request_queue中。

        2. 内核处理请求队列,并执行bio中的请求。

bio创建后,调用struct request_queue中make_request_fn函数指针,将新请求加入请求队列。

而request_fn用于提交请求。

1. 创建IO请求

submit_bio:

        根据bio创建一个新request。

        使用make_request_fn将request加入到request_queue中。

2. 队列插入

为提高IO性能,尽可能重排或合并各个请求。

队列空闲时:处理队列中请求。否则只添加请求到队列,而不处理。

请求插入队列后,后续何时处理请求?

       1. 定时器。
        2. 请求超过阈值。

3. 执行请求

执行请求:

        struct request_queue->request_fn()函数指针。

struct request_queue    *blk_init_queue(request_fn_proc     *rfn,     spinlock_t     *lock)

        用于设置request_fn()函数指针。

        不同设备驱动中调用该函数设为不同函数。

6.5.8 I/O调度

I/O调度器:也叫电梯。

        用于调度和重排磁盘IO读写操作请求。以优化磁盘访问的顺序和效率。

一个调度器包含的操作:

struct elevator_ops {

        elevator_merge_fn                 *elevator_merge_fn;

                //检查新请求是否可以和现有请求合并。

        elevator_merged_fn                 *elevator_merged_fn;

                //合并后调用。

        elevator_merge_req_fn         *elevator_merge_req_fn;

                //执行请求合并。

        elevator_allow_merge_fn         *elevator_allow_merge_fn;

                //是否可以将当前请求与现有请求合并。

        elevator_bio_merged_fn         *elevator_bio_merged_fn;

                //当一个bio被合并到一个请求中时调用。

        elevator_dispatch_fn                 *elevator_dispatch_fn;

                //从指定队列中选择下一个调度的请求给设备驱动。

        elevator_add_req_fn                 *elevator_add_req_fn;

                //向队列添加请求。

        elevator_activate_req_fn                 *elevator_activate_req_fn;

        elevator_deactivate_req_fn             *elevator_deactivate_req_fn;

                //当请求变为活动/非活动时调用。

        elevator_completed_req_fn         *elevator_completed_req_fn;

                //当一个请求完成时调用。

        elevator_init_icq_fn                 *elevator_init_icq_fn;

        elevator_exit_icq_fn                 *elevator_exit_icq_fn;

                //初始化/清理 I/O上下文队列。

        elevator_set_req_fn                 *elevator_set_req_fn;

        elevator_put_req_fn                 *elevator_put_req_fn;

        elevator_may_queue_fn         *elevator_may_queue_fn;

                //是否可将请求添加到请求队列。

        elevator_init_fn                 *elevator_init_fn;

        elevator_exit_fn                 *elevator_exit_fn;

                //调度器初始化时、退出时调用。

}

请求上下文(I/O Context Queue, ICQ):

        ICQ 存储与请求相关上下文,如文件系统元数据、锁状态等。

表示一个调度器:

struct         elevator_type

{

        struct kmem_cache         *icq_cache;

        struct elevator_ops         ops;

        size_t                             icq_size;

        size_t                             icq_align;

        struct elv_fs_entry         *elevator_attrs;         //sysfs中的属性。

        char                                 elevator_name[ELV_NAME_MAX];         //调度器名称。

        struct module                 *elevator_owner;

        struct list_head                 list;         //连接所有IO调度器。

};

内核的IO调度器有:

        1. elevator_noop:

                简单,先来先服务。可合并请求,但不能重排。

                使用场景:

                        1. 可自行重排的智能硬件。

                        2. 不用寻道的设备, 如闪存。

        2. iosched_deadline:

                目的:

                        最小化寻道次数。

                        尽可能在一定时间内完成。

        3. iosched_cfq:

                完全公平队列。默认调度器。

                每个进程有一个队列,轮询调度多个队列。

拓展

常见I/O调度算法:

        完全公平队列(CFQ):

                为每个进程提供公平访问磁盘机会。将磁盘带宽分配给不同进程。

                适用于多任务公平共享磁盘资源环境。

        Deadline:

                适用于低延迟应用,如实时应用,数据库。

        Noop:

                不重排序不优化。

                适用不需要额外调度开销的情况,如SSD设备。

        电梯算法:

                优化了磁盘访问顺序,减少寻道时间。

                模拟电梯上下移动,根据磁头当前位置和移动方向,调度最近请求 。

                对于磁盘访问密集型且随机的I/O,显著提高性能。

                缺点:

                        当磁头频繁改变方向时,一些请求可能长时间等待。

                        因此需要根据实际应用的特点和需求权衡。

6.5.9 ioctl实现

系统调用 - > sys_ioctl -> vfs_ioctl

blkdef_ioctl:实现了某些ioctl,对于所有块设备都可用。

        如:读取设备分区信息,设备总长度。

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

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

相关文章

curl发送邮件需要哪些参数设置?如何配置?

curl发送邮件有哪些认证方式?如何通过curl命令发信? curl是一个命令行工具,用于在网络上传输数据,包括发送电子邮件。要使用curl发送邮件,需要设置一些参数以确保邮件被正确发送到目标收件人。AokSend来介绍一些必需的…

【Unity】Animator动画倒播,与StartRecording动画录制

一、Animator动画倒播 正常我们修改速度,只需要修改Animator.speed即可,但如果设置为负值,Animator系统会自动将其改为0值。 1.创建动画速度参数 (1)设置动画 我们需要创建表示速度的动画参数Speed,将其付给需要倒播的动画片段…

改进位删除谜题的求解方法

问题背景 给定长度为 n 的二进制向量,如何删除恰好 n/3 个位,使剩余二进制向量的不同数量最小化。该问题被称为“位删除谜题”。 以下是该问题的示例: 对于 n 3 的情况,最优解是 2,对应两个不同的向量 11 和 00。对…

韩国裸机云站群服务器托管租用方案

随着网络技术的飞速发展,站群服务器在网站运营中扮演着越来越重要的角色。韩国裸机云站群服务器,以其独特的优势,如地理位置优越、价格相对较低、技术实力雄厚等,吸引了众多企业的关注。本文将为您详细介绍韩国裸机云站群服务器的…

如何快速翻译pdf英文论文(5分钟就可以翻译一篇几十页的英文论文)

一、问题:如何快速翻译pdf英文论文 二、解决方法: 可以通过下面三个在线翻译来进行翻译pdf文档 百度翻译有道翻译谷歌翻译 方法:以有道翻译为例,可以直接百度搜索有道在线翻译,然后点击文档翻译,将pdf文…

Python抓取天气信息

Python的详细学习还是需要些时间的。如果有其他语言经验的,可以暂时跟着我来写一个简单的例子。 2024年最新python教程全套,学完即可进大厂!(附全套视频 下载) (qq.com) 我们计划抓取的数据:杭州的天气信息…

docker pull xxx拉取超时time out

文章目录 前言总结 前言 换了镜像源,改配置的都不行,弄了一个下午,最后运行一下最高指令就可以了 sudo docker_OPTS"--dns 8.8.8.8"总结 作者:加辣椒了吗? 简介:憨批大学生一枚,喜欢…

02-ES6新语法

1. ES6 Proxy与Reflect 1.1 概述 Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。 Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,…

WEB3-众筹合约

构建众筹合约的框架,包括定义 IERC20 接口,并通过构造函数初始化代币合约。 By:HackQuesthttps://www.hackquest.io/zh

如何用Vue3和ApexCharts打造引人注目的3D径向条形图

本文由ScriptEcho平台提供技术支持 项目地址:传送门 使用 ApexCharts 构建美观的 Vue.js 径向条形图 应用场景 径向条形图是一种用于可视化单一数据点及其与目标或理想值的关系的图表类型。它在显示进度、完成率或其他类似度量时非常有用。 基本功能 这段代码…

同三维T80002JEHV H.265高清解码器

同三维T80002JEHV H.265高清解码器 1路HDMI1路VGA解码输出,1/2/4画面分割或16路轮询显示 产品简介: 同三维T80002JEHV解码器使用Linux系统,支持VGA/HDMI二种接口同时输出,支持多流输入多流解码及多屏显示,具有完善的…

Django REST framework数据展示技巧:分页、过滤与搜索的实用配置与实践

系列文章目录 Django入门全攻略:从零搭建你的第一个Web项目Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解Django ORM深度游&#xff1…

【修复Win11错误 0x80010135: 路径太长】

1. 问题现象: 一个意外错误使你无法复制该文件。如果你继续收到此错误,可以使用错误代码来搜索有关此问题的帮助。 错误 0x80010135: 路径太长 或者这样 2. 分析问题 造成这个问题的主要原因包括: 文件路径长度超过 260 个字符&#xf…

Qt利用Coin3D(OpenInventor)进行3d绘图

文章目录 1.安装1.1.下载coin3d1.2.下载quarter1.3.解压并合并 2.在Qt中使用3.画个网格4.加载wrl模型 1.安装 1.1.下载coin3d 首先,到官网下载[coin3d/coin] 我是Qt5.15.2vs2019的,因此我选择这个coin-4.0.2-msvc17-x64.zip 1.2.下载quarter 到官网…

【信息资源组织与管理】【开卷考】如何准备 期末考试复习必备

索引篇 先去xhs找了开卷考有什么准备技巧,来自Prozac ❗️首先,适用于考试范围为课本内容或者课堂内容,如果有那种拓展题,脱离课本的,那我就没办法了。 ✅一定要熟悉熟悉熟悉课本 1. 第一遍略看课本,可以不…

万界星空科技QMS质量管理介绍

产品的生产质量是企业发展之根本,对所有企业来说,建立完善质量控制体系,对企业生产经营以及发展竞争具有至关重要的影响,可以说是企业质量保证的防火墙。QMS质量管理系统对任何一家企业都具有重要意义,可帮助企业提高生…

shell脚本监控docker容器和supervisor 运行情况

1.ASR服务 需求: 在ASR服务器中 docker 以下操作中 忽略容器名字叫 nls-cloud-mongodb 的容器 在ASR服务器中 docker ps 查看正在运行的容器 docker stats -a --no-stream 可以监控容器所占资源 确认是否有pid且不等于0 docker inspect -f “{{.RestartCount}}” 容器名称 可…

为何Proteus用户争相拥抱SmartEDA?揭秘背后的强大吸引力!

在电路设计与仿真领域,Proteus一度以其稳定性能和丰富功能赢得了众多用户的青睐。然而,近年来,越来越多的Proteus用户开始转向SmartEDA,这一新兴电路仿真软件正迅速崭露头角,成为行业内的翘楚。那么,究竟是…

【Java】已解决java.util.ConcurrentModificationException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.util.ConcurrentModificationException异常 一、分析问题背景 java.util.ConcurrentModificationException异常是Java集合框架中常见的一个运行时异常。这个异常通常会…

llama-factory微调工具使用入门

一、定义 环境配置案例: https://zhuanlan.zhihu.com/p/695287607chatglm3 案例多卡训练deepspeedllama factory 案例Qwen1.5报错 二、实现 环境配置 git clone https://github.com/hiyouga/LLaMA-Factory.git conda create -n llama_factory python3.10 conda …