0

【驱动】块设备驱动(一)-驱动框架 - 嵌入式与Linux那些事

 3 months ago
source link: https://www.cnblogs.com/dongxb/p/18007808
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

块设备的定义

块设备是针对存储设备的,比如 SD 卡、EMMC、NAND Flash、Nor Flash、SPI Flash、机械硬盘、固态硬盘等。因此块设备驱动其实就是这些存储设备驱动,块设备驱动相比字符设备相比,块设备有以下几个特殊之处:

  1. 块设备可以从数据的任何位置进行访问
  2. 块数据总是以固定长度进行传输,即便请求的这是一个字节
  3. 对块设备的访问有大量的缓存。当进行读时,如果已经缓存了,就直接使用缓存中的数据,而不再读设备,对于写也通过缓存来进行延迟处理。

块设备读写是按块(所以叫块设备)进行的,使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区。作为存储设备,块设备驱动的核心问题就是哪些page->segment->block->sector与哪些sector有数据交互,下图是Linux内核中块设备的驱动模型。

块设备驱动框架

1421380-20240205133858652-2098896344.png
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

虚拟文件系统

虚拟文件系统(VFS)隐藏了各种硬件的具体细节,为用户操作不同的硬件提供了一个统一的接口。其基于不同的文件系统格式,比如EXT,FAT等。用户程序对设备的操作都通过VFS来完成,在VFS上面就是诸如open、close、write和read的函数API。

映射层(mapping layer):这一层主要用于确定文件系统的block size,然后计算所请求的数据包含多少个block。同时调用具体文件系统函数来访问文件的inode,确定所请求的数据在磁盘上面的逻辑地址。

通用块层是 Linux 内核中的中间层,位于块设备驱动层和文件系统层之间。通用块层负责维持一个I/O请求在上层文件系统与底层物理磁盘之间的关系。在通用块层中,通常用一个bio结构体来对应一个I/O请求。通用块层隐藏了底层硬件的细节,使上层的软件可以独立于具体的硬件实现。它还负责管理块设备的缓存、缓冲区和数据传输,以提高性能。

IO调度层

IO调度层是通用块层的一部分,它负责决定块设备上的IO请求的执行顺序。当多个IO请求同时到达块设备时,IO调度层使用调度算法来决定哪个IO请求应该首先执行。调度算法的目标是优化系统的性能和响应速度。常见的IO调度算法包括:

  • CFQ(完全公平队列):根据进程的IO请求历史和权重来调度IO请求。它试图公平地分配磁盘带宽给不同的进程。
  • Deadline(截止时间):使用截止时间来调度IO请求。它将IO请求分为读取和写入,并尽量在截止时间之前完成IO请求。
  • NOOP(无操作):简单地将IO请求按照先到先服务的方式进行调度,不做任何优化。

块设备驱动层

在Linux中,驱动对块设备的输入或输出(I/O)操作,都会向块设备发出一个请求,在驱动中用request结构体描述。但对于一些磁盘设备而言请求的速度很慢,这时候内核就提供一种队列的机制把这些I/O请求添加到队列中(即:请求队列),在驱动中用request_queue结构体描述。在向块设备提交这些请求前内核会先执行请求的合并和排序预操作,以提高访问的效率,然后再由内核中的I/O调度程序子系统来负责提交 I/O 请求, 调度程序将磁盘资源分配给系统中所有挂起的块 I/O 请求,其工作是管理块设备的请求队列,决定队列中的请求的排列顺序以及什么时候派发请求到设备。

页、段、块、扇区关系

  • 扇区(Sectors):任何块设备硬件对数据处理的基本单位。通常,1个扇区的大小为512byte。(对设备而言)
  • 块 (Blocks):由Linux制定对内核或文件系统等数据处理的基本单位。通常,1个块由1个或多个扇区组成。(对Linux操作系统而言)
  • 段(Segments):是一个内存页或内存页的一部分,它包含磁盘上物理相邻的几个数据块的内容,是块驱动的传送单位,大小不定(取决于通用块层,因为它把传送的数据下发给块驱动,而通用块还可以把几个段合并成物理段、硬件段(专门总线电路);同时也取决于用户所访问的大小。注意这里所指的段与内存中的段也有些联系,因为内存的段可能是一个对象/变量的大小;而用户程序也可能以变量/对象作为单位来访问设备。
  • 页(page):在这里仅仅是把4096B的连续数据称为一个页。也可以指内存的数据组织单位(有些体系还在使用段,但是多数已经将段屏蔽了,即内部使用,而外部“看不见"),大小通常为4096B。但内存本身的访问/传送单位并不是页,这是取决于内存的编址方法,现在内存通常是按字节编址的,而甚至部分可以按位编址,所以内存的访问单位可以更小。
  • 页、段、块、扇区之间的关系图如下:
块设备驱动-第 2 页.drawio

https://zhuanlan.zhihu.com/p/507214979

https://zhuanlan.zhihu.com/p/504763396

https://zhuanlan.zhihu.com/p/87566255

https://www.cnblogs.com/lifexy/p/7651667.html

https://cloud.tencent.com/developer/article/2145712


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK