如何在Linux系统中有效管理和优化块设备的读写性能?

请求处理函数的触发条件

1、读操作

如何在Linux系统中有效管理和优化块设备的读写性能?插图1
(图片来源网络,侵删)

读取数据:当应用程序执行文件读取操作(如read函数)时,会向文件系统发送读取请求,并触发请求处理函数中的读操作。

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

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

2、写操作

写入(追加、更新)的写入(write)和追加(append)会向文件系统发送写入请求,并触发请求处理函数中的写操作。

如何在Linux系统中有效管理和优化块设备的读写性能?插图3
(图片来源网络,侵删)

文件创建:当应用程序创建一个新文件时,它会向文件系统发送创建文件的请求,并触发请求处理函数中的写操作。

从请求队列获取请求

1、方式一:获取 + 开启请求

获取请求:使用APIblk_peek_request 来获取请求。

开启请求:使用APIblk_start_request 来开启请求。

如何在Linux系统中有效管理和优化块设备的读写性能?插图5
(图片来源网络,侵删)

2、方式二:一步到位

获取 + 开启请求:使用APIblk_fetch_request,该函数实际上是对上述两个函数的使用做了一层封装。

开始进行读写操作

1、请求的结构

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

2、相关API

获得扇区起始地址sector_t blk_rq_pos(const struct request *rq);

获取请求所涉及的数据长度unsigned int blk_rq_bytes(const struct request *rq);

获取指定数据页的线性地址void *bio_data(struct bio *bio);

获取当前请求的数据传输方向int rq_data_dir(struct request *rq);

关闭请求

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

完整代码示例

// 示例代码省略,通常包括打开设备、设置权限、编写读写程序等步骤。

块设备 VS 字符设备

块设备是具有一定结构的随机存取设备,对这种设备的读写是按块进行的,使用缓冲区来存放暂时的数据。

大多数情况下,磁盘控制器都是直接使用DMA方式进行数据传送。

IO调度

IO调度就是电梯算法,磁盘的读写是通过机械性的移动磁头来实现的,理论上磁盘设备满足块设备的随机读写的要求,但是出于节约磁盘和提高效率的考虑,我们希望当磁头处于某一个位置的时候,一起将最近需要写在附近的数据写入,而不是这写一下。

内核中的块设备驱动模型

块设备驱动的核心问题是哪些page->segment->block->sector与哪些sector有数据交互。

用户态程序通过open()打开指定的块设备

用户态程序通过open()打开指定的块设备,通过systemcall机制陷入内核,执行blkdev_open()函数,该函数注册到文件系统方法(file_operations)中的open上。

数据流操作

用户的数据是如何到内核的,每种设备类型底层操作方法是不一样的,但是通过file_operations方法将设备类型的差异化屏蔽了,这就是Linux能够将所有设备都理解为文件的原因。

块设备接口

块设备接口很简单,接口方法为submit_bio(更底层函数为generic_make_request),数据结构为struct bio。

以上内容就是解答有关linux块设备读写的详细内容了,我相信这篇文章可以为您解决一些疑惑,有任何问题欢迎留言反馈,谢谢阅读。

本文来源于互联网,如若侵权,请联系管理员删除,本文链接:https://www.9969.net/73875.html

小末小末
上一篇 2024年10月11日 19:12
下一篇 2024年10月11日 19:25

相关推荐