【Linux驱动】块设备驱动(二)—— 块设备读写(使用请求队列)

news2024/10/5 19:12:16

块设备的操作函数并没有类似于字符驱动中的read 和write函数,要实现读写操作,只能在请求处理函数中实现。这就分为两种,是否要使用请求队列,请求队列的主要作用是管理和调度IO请求。在以下情况中,一般需要用到请求队队列:

  • 多任务环境:多个任务同时对存储设备进行读写,请求队列可以对IO请求进行排序和调度
  • 磁盘优化:磁盘是一种机械设备,其IO操作需要进行磁盘寻道等操作,非常耗时,请求队列可以将多个IO请求进行合并,可以减少磁盘的寻道次数,提高磁盘的吞吐量。

因此,本篇的重点便是使用请求队列来实现块设备的读写操作。


目录

一、请求处理函数的触发条件

二、从请求队列获取请求

三、开始进行读写操作

1、请求的结构

2、相关API

四、关闭请求

五、完整代码


一、请求处理函数的触发条件

若要对块设备进行读写操作,需要触发请求处理函数,随后块设备驱动才会调度并处理请求。那么在什么情况下会触发请求处理函数?以下是读写操作的常见触发条件。

读操作

一般涉及到访问文件内容、文件属性、文件权限的时候,会触发请求处理函数中的读操作。

① 读取数据

当应用程序执行文件读取操作(如 read 函数)时,它会向文件系统发送读取请求,并触发请求处理函数中的读操作。每一个请求内包含源数据(块设备扇区地址、读取字节数)以及目的地址(内存页地址、页偏移)。文件系统从块设备读取相应的文件块数据,并将其返回给应用程序。

② 目录遍历

当应用程序执行目录遍历操作(如 opendir、readdir 函数等)时,文件系统会在磁盘上读取目录的元数据,并返回给应用程序。

③打开文件

当应用程序打开一个文件时,文件系统需要读取磁盘上的文件元数据信息,如文件大小、访问权限等,以供应用程序使用。

写操作

一般涉及到文件内容的更新、文件创建等操作时,会触发请求处理函数中的写操作。

① 文件内容写入(追加、更新)

文件内容的写入(write)和追加(append)会向文件系统发送写入请求,并触发请求触发函数中的写操作。每一个请求内包含源数据(内存页地址、页偏移)以及目的地址(块设备扇区地址),文件系统会将应用程序提供的数据写入到指定扇区。

此外,除了文件内容的更新,文件属性(如访问权限)的更新也会触发请求处理函数。

② 文件创建

当应用程序创建一个新文件时,它会向文件系统发送创建文件的请求,并触发请求处理函数中的写操作。文件系统在磁盘上为新文件分配空间,并更新文件的元数据信息。

二、从请求队列获取请求

接下来便是正式开始实现请求处理函数,函数的形参为请求队列,对此,下面的第一步便是从请求队列中获取请求。涉及的API 在 <linux/blkdev.h>

void request_handle(struct request_queue *q);

① 方式一:获取 + 开启请求

正常来说,获取请求包含两步,第一步是获取请求,使用的API为 blk_peek_request

/**
 * @param q 请求队列
 * @return 成功返回获取到的请求结构体地址,失败返回 NULL
 */
struct request *blk_peek_request(struct request_queue *q);

获取到请求以后,还没结束,需要开启请求,目的是将通知硬件设备开始处理当前请求,同时将当前请求标记为启动状态,以确保请求在处理的过程中不会被打断。其他还有数据预处理、设备准备等原因。

/**
 * @param rq 获取到的请求
 */
void blk_start_request(struct request *rq);

② 方式二:一步到位

Linux内核提供了获取 + 开启一步到位的方式,使用的API为 blk_fetch_request,该函数其实就是对上述两个函数的使用做了一层封装。

/**
 * @param q 请求队列
 * @return 成功返回获取到的请求结构体地址,失败返回 NULL
 */
struct request *blk_fetch_request(struct request_queue *q);
/*
struct request *blk_fetch_request(struct request_queue *q)
{
    struct request *rq;

    rq = blk_peek_request(q);
    if (rq)
        blk_start_request(rq);
    return rq;
}
*/

三、开始进行读写操作

在开始读写操作之前,需要先了解每一个请求的结构,因为既然要进行读写操作,我们需要知道源数据地址、目的地址、操作的字节数等信息。

1、请求的结构

每个request 中保存了多个 bio,bio保存着最终要读写的数据、地址等信息。bio 中的 bvec_iter 保存了块设备扇区起始地址、扇区大小等信息,bio 中的 bio_vec 保存了 RAM 页地址、剩余页长度以及页偏移等信息。

下面是 biobio_iter bio_vec 三者之间的关系

2、相关API

获得扇区起始地址

/**
 * @param rq 指向请求结构体的指针
 * @return   成功返回获取到的扇区起始地址
 */
sector_t blk_rq_pos(const struct request *rq);

 获取请求所涉及的数据长度

/**
 * @param rq 指向请求结构体的指针
 * @return   成功返回数据长度,单位:字节
 */
unsigned int blk_rq_bytes(const struct request *rq);

获取指定数据页的线性地址,即 RAM 中的起始页地址

/**
 * @param bio 指向bio结构体的指针
 * @return    成功返回指向指定数据页的地址
 */
void *bio_data(struct bio *bio);

获取当前请求的数据传输方向(读操作、写操作)

/**
 * @param rq 指向请求结构体的指针
 * @return   返回数据传输方向。可以是 READ / WRITE
 */
int rq_data_dir(struct request *rq);

四、关闭请求

与前面开启请求相对应,开启请求后将当前请求标记为开启状态,以确保在处理请求的过程中不会被打断;关闭请求意味着该请求的数据传输和相关操作已经完成,主要目的有两点:

  • 通知请求完成:通知相关的应用程序或调用者操作已经结束,允许继续执行后续的操作
  • 资源释放:在请求处理完成后,需要释放请求所占用的内存和其他资源,以便系统能够重新利用这些资源。

这里可以使用 __blk_end_request_cur 或者 blk_end_request_cur,两个函数的使用方法完全一样,他们之间的区别在于

① __blk_end_request_cur

__blk_end_request_cur是一个异步函数,它会立即结束当前的 I/O 请求,并触发相应的回调函数(例如,end_io)来进行后续处理。这意味着调用 __blk_end_request_cur 并不会等待请求的处理完成,而是立即返回,将请求的处理交给后续的回调函数来处理。

② blk_end_request_cur

blk_end_request_cur 与上面相反,是一个同步函数,它会等待当前的 I/O 请求的处理完成,并在处理完成后返回。它会等待直到请求的 end_io 回调函数执行完毕,或者出现超时或错误等情况。因此,在调用 blk_end_request_cur 的过程中,它会阻塞当前的执行线程,直到请求处理完成。

/**
 * @param rq     指向请求结构体的指针
 * @param error  代表请求处理结果,
 *               - 若请求处理成功,应该将 error 设置为 0
 *               - 若请求处理失败,则可以设置为其他非零值。
 */
bool __blk_end_request_cur(struct request *rq, int error);

五、完整代码

将驱动代码重新编译并加入到内核,输入 fdisk -l,我们会发现请求处理函数被触发了,因为 fdisk -l 用于列出当前系统中所有的磁盘分区信息,在扫描设备的过程中,会涉及块设备的访问和信息读取,这就导致了请求处理函数被触发。

void request_handle(struct request_queue *q)
{
    printk("请求处理函数被触发!\n");

    struct request* req;                // 处理请求
    int errors = 0;                     // 请求处理状态
    sector_t start = 0;                 // 操作扇区的起始地址
    int len = 0;

    while ((req = blk_fetch_request(q)) != NULL)
    {
        // 获得扇区起始地址
        start = blk_rq_pos(req);
        // 当前请求所涉及的字节数
        len = blk_rq_cur_bytes(req);
        // 获得bio结构体中的缓冲区指针
        void* buffer = bio_data(req->bio);
        
        // 判断是读操作还是写操作
        if (rq_data_dir(req) == READ)
        {
            memcpy((uint8_t*)buffer, blkdev.diskbuf, len);
            printk("从块设备读数据\n");
        }
        else if(rq_data_dir(req) == WRITE)
        {
            memcpy(blkdev.diskbuf, (uint8_t*)buffer, len);
            printk("向块设备写数据\n");
        }
        
        // 结束当前请求
        __blk_end_request_cur(req, errors);
    }
}

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

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

相关文章

Kafka 使用手册

kafka3.0 文章目录 kafka3.01. 什么是kafka&#xff1f;2. kafka基础架构3. kafka集群搭建4. kafka命令行操作主题命令行【topic】生产者命令行【producer】消费者命令行【consumer】 5. kafka生产者生产者消息发送流程Producer 发送原理普通的异步发送带回调函数的异步发送同步…

虚幻5源码版打包服务端

适用情况&#xff0c;windows系统&#xff0c;已经安装vs2022之类的&#xff0c;和UE5适配的版本 源码版使用 1.下载源码版&#xff0c;推荐下载 压缩包 tar.gz那个&#xff0c;zip和git clone我老是下载不下载来&#xff0c;只是这个压缩包要解压1个多小时… 2.点击 源码的…

C语言-4

排序算法简介 /*学习内容&#xff1a;冒泡排序&#xff08;最基本的排序方法&#xff09;选择排序&#xff08;冒泡的优化&#xff09;插入排序&#xff08;在合适的位置插入合适的数据&#xff09; *//*排序分类&#xff1a;1.内部排序待需要进行排序的数据全部存放到内存中&…

【Python基础】案例分析:电商分析

电商分析 1 案例:某年淘宝双12部分购物数据 1.1 数据&#xff1a;某年淘宝双12部分购物数据&#xff1b; 来源&#xff1a;天池数据平台 1.2 分析目的&#xff1a; 熟悉电商常用分析指标用户行为分析用户价值模型 2 熟悉数据 2.1 导入数据 import pandas as pd fpath …

Vscode编译运行多个C++文件

1.摘要 在使用Vscode编译单个文件网上很多教程&#xff0c;但是对多个文件编译会发现经常出问题&#xff0c;通过不断的借阅网友的教程改进终于完成C运行多个文件教程如下&#xff1a; 2.编译运行过程 2.1 初始配置过程 &#xff08;1&#xff09;Vscode以及MinGW配置教程很…

EasyRecovery数据恢复软件2024最新特别绿色版下载

EasyRecovery数据恢复软件是一款功能强大的工具&#xff0c;最新版本通常包含更多优化和新增功能&#xff0c;以提升用户体验和数据恢复成功率。由于软件版本会不断更新&#xff0c;我无法提供特定于最新版本的详细介绍&#xff0c;但我可以概述EasyRecovery的一般功能以及下载…

20240206在WIN10下下载安装RX580的驱动程序

20240206在WIN10下下载安装RX580的驱动程序 2024/2/6 19:24 百度搜索&#xff1a;RX580 驱动 我用的是X99主板的渲染服务器&#xff0c;只能装WIN10的64位系统。直接下载并安装最新的驱动程序就可以了&#xff01; 另&#xff1a;我以前的电脑插的是RX550的显卡&#xff0c;直接…

推动海外云手机发展的几个因素

随着科技的不断发展&#xff0c;海外云手机作为一种新兴技术&#xff0c;在未来呈现出令人瞩目的发展趋势。本文将在用户需求、技术创新和全球市场前景等方面&#xff0c;探讨海外云手机在未来的发展。 1. 用户需求的引领&#xff1a; 随着人们对移动性和便捷性的需求不断增长&…

【数据结构和算法】--- 基于c语言排序算法的实现(1)

目录 一、排序的概念及其应用1.1排序的概念1.2 排序的应用1.3 常见的排序算法 二、插入排序2.1直接插入排序2.2 希尔排序2.2.1 预排序2.2.2 缩小gap2.2.3 小结 三、选择排序3.1 直接选择排序3.2 堆排序 一、排序的概念及其应用 1.1排序的概念 排序&#xff1a; 所谓排序&…

R语言 Error in make.names(col.names, unique = TRUE) : invalid multibyte string at ‘<b1><ea><cc><e2>‘

R语言导入CSV文件的时候&#xff0c;代码如下&#xff1a; data<-read.csv("data.csv") 出现以下报错&#xff1a; Error in make.names(col.names, unique TRUE) : invalid multibyte string at <b1><ea><cc><e2> Error in make.n…

LeetCode、17. 电话号码的字母组合【中等,dfs回溯】

文章目录 前言LeetCode、17. 电话号码的字母组合【中等&#xff0c;dfs回溯】题目与类型思路递归回溯优化&#xff1a;StringBuilder来回溯补充代码&#xff1a;2024.1.31&#xff08;简化&#xff09; 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博…

Transformer实战-系列教程6:Vision Transformer 源码解读4

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 Vision Transformer 源码解读1 Vision Transformer 源码解读2 Vision Transformer 源码解读3 Vis…

mac检查CPU温度和风扇速度软件:Macs Fan Control Pro 1.5.17中文版

Macs Fan Control Pro for Mac是一款专业的电脑风扇控制工具&#xff0c;旨在帮助Mac用户有效控制电脑的风扇速度&#xff0c;提高电脑的运行效率和稳定性。 软件下载&#xff1a;Macs Fan Control Pro 1.5.17中文版 该软件支持多种风扇控制模式和预设方案&#xff0c;用户可以…

【leetcode】206. 反转链表(简单)题解学习

题目描述&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 …

VLM 系列——Llava1.6——论文解读

一、概述 1、是什么 Llava1.6 是llava1.5 的升级暂时还没有论文等&#xff0c;是一个多模态视觉-文本大语言模型&#xff0c;可以完成&#xff1a;图像描述、视觉问答、根据图片写代码&#xff08;HTML、JS、CSS&#xff09;&#xff0c;潜在可以完成单个目标的视觉定位、名画…

【JavaScript 漫游】【006】数据类型 array

文章简介 本文为【JavaScript 漫游】专栏的第 006 篇文章&#xff0c;记录笔者在了解 JS 数据类型 array 中摘录的知识点。 数组的本质是对象属组的 length 属性for ... in 循环和数组的遍历数组的空位类数组对象 除了上述 5 个重要知识点&#xff0c;学习数组更为重要的是掌…

MySQL组复制的介绍

前言 本文介绍关于MySQL组复制的背景信息和基本原理。包括&#xff0c;介绍MySQL传统复制方法的原理和隐患、介绍组复制的原理&#xff0c;单主模式和多主模式等等。通过结合原理图学习这些概念&#xff0c;可以很好的帮助我们理解组复制技术这一MySQL高可用方案&#xff0c;有…

Linux系统中安装JDK

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

深入探究:JSONCPP库的使用与原理解析

君子不器 &#x1f680;JsonCPP开源项目直达链接 文章目录 简介Json示例小结 JsoncppJson::Value序列化Json::Writer 类Json::FastWriter 类Json::StyledWriter 类Json::StreamWriter 类Json::StreamWriterBuilder 类示例 反序列化Json::Reader 类Json::CharReader 类Json::Ch…

VScode上无法运行TSC命令,Typescript

如何解决问题 第一步&#xff1a;使用 winx 快捷键&#xff0c;会出现如下弹窗&#xff0c;鼠标左键单击Windows PowerShell 即可打开shell 第二步&#xff1a;运行 set-ExecutionPolicy RemoteSigned 命令&#xff0c;在询问更改执行策略的时候选择敲Y或者A 第三步&#xff…