第十四章 块设备驱动
本章讲述的是块设备的I/O驱动。块设备的关键点是在CPU和总线读写数据所使用的时间和硬盘速度上的不同。块设备平均访问时间很高。每个操作需要几毫秒才能完成,主要因为磁盘控制器必须把磁盘头从磁盘表面移到记录数据的确切位置。然而,一旦磁盘头准确到位了,数据传输可以维持在较快的速度。
14.1 块设备处理
每个对块设备驱动的操作涉及到大量的内核组件;其中最重要的几个组件展示在图14-1。
图 14-1 一个块设备操作影响到的内核组件
VFS
Disk Caches
Mapping Layer (Disk Filesystem Block Device File )
Generic Block Layer
I/O scheduler layer
Block Device Driver
Hard Disk
让我们假设一个进程向一些磁盘文件发出一个read()系统调用,下面是内核处理该请求的典型步骤:
1. read()系统调用的服务程序激活一个合适的VFS函数,传递给它文件描述符和文件偏移。虚拟文件系统层是整个块设备处理框架的最上层,它提供一个Linux支持的所有文件系统都采用的通用文件模型。
2. VFS函数来决定请求的数据是否有效,如果必要的话,还要决定怎样实现该读操作。有时不需要访问磁盘上的数据,因为内核把最近从块设备读的或者写到块设备的内容保存在RAM中,就是磁盘缓存(Disk Caches)机制。
3. 我们假设内核必须从块设备(磁盘)中读取数据,因此它必须决定数据在磁盘上的物理位置,这依靠映射层通过以下两步来完成:
a.它决定文件所属文件系统的块大小并且根据文件块号(file block numbers)计算请求数据的内容。本质上,文件可以看成是分成多个块,内核来决定包含请求数据的块的号码(相对于文件起始块的号码)。
b.接下来,映射层调用文件系统相关的函数来访问文件的磁盘节点并且根据逻辑块号(logic block numbers)来决定请求数据在磁盘上的位置。由于一个文件可能存储在非相邻的磁盘块上,磁盘节点中存储着一个数据结构用来映射文件块号到逻辑块号。
4.内核现在可以处理对块设备的读操作。它利用通用块层(generic block layer)启动IO操作来传输请求数据。通常情况下,每个IO操作涉及到磁盘上邻近的多个块。因为请求的数据可能在磁盘上不是邻近的,那么通用块层可能会启动多个IO操作。每个IO操作都由一个"block I/O"结构表征,它收集底层组件所需要的信息来完成请求。
14.1.1 扇区
14.2 通用块层