IO层次结构以及每层的作用
I/O层次结构及各层作用
第一层:用户层I/O软件 (User-Level I/O Software)
-
作用: 这一层是与用户程序直接交互的部分。它为程序员提供了简单、易用的接口(API),并将这些调用转换为对操作系统的服务请求(即系统调用)。它还可能涉及数据的格式化和用户态的缓冲。
-
在本例中的作用:
-
程序员编写的代码是
read(fd, buf, 100)
。这是一个标准的库函数调用。 -
C库(
libc
)中的read
函数实现,会将这些参数(文件描述符、缓冲区地址、字节数)打包好,然后通过一个陷入(trap)指令,触发一个系统调用,请求内核提供读文件服务。 -
简单来说,这一层就是我们编程时使用的
printf
、scanf
、read
、write
等函数,它们是通往操作系统内核的大门。
-
第二层:设备无关的操作系统软件 (Device-Independent OS Software)
-
作用: 这是操作系统内核中处理I/O的核心部分,其目标是提供一个统一的框架来管理所有设备,而无需关心具体设备的细节。它的职责包括:
-
统一接口: 为所有设备驱动提供一个统一的接口(如都支持
open
,read
,write
等)。 -
设备命名与保护: 将文件路径(如
/home/user/data.txt
)映射到具体的设备和文件。 -
缓冲与高速缓存 (Buffering/Caching): 为了提高性能,实现内核I/O缓冲区(页高速缓存),减少对物理设备的访问次数。
-
差错处理: 提供通用的错误报告和处理框架。
-
-
在本例中的作用:
-
系统调用进入内核后,这一层开始工作。它根据文件描述符
fd
找到对应的文件信息,确定需要读取的是磁盘上的哪个文件,以及从文件的哪个偏移位置开始读取。 -
它计算出这100个字节的数据对应于文件的哪个逻辑块。
-
(关键步骤) 它首先检查内核的页高速缓存,看看这个逻辑块是否已经存在于内存中。
-
如果命中缓存:直接从内存中复制数据到用户缓冲区,整个I/O请求可能就此完成,无需访问磁盘。
-
如果未命中缓存:它必须向下一层发出请求。它会将“文件的逻辑块号”转换为“设备的物理块号”,然后向磁盘的设备驱动程序发出一个通用的、与具体磁盘型号无关的命令,例如:“请读取逻辑块号为
LBA 12345
的数据”。
-
-
第三层:设备驱动程序 (Device Drivers)
-
作用: 这是与硬件直接相关的“翻译官”。它接收来自上层(设备无关层)的抽象命令,并将其翻译成特定硬件控制器能够理解的具体指令。每个设备(如NVIDIA的显卡、Intel的SATA控制器)都有其专属的驱动程序。
-
在本例中的作用:
-
磁盘的设备驱动程序收到了“读取逻辑块号
LBA 12345
”的命令。 -
驱动程序知道当前计算机上安装的是哪款硬盘,以及如何与其控制器通信。
-
它将抽象的块号转换为该硬盘能懂的柱面号(Cylinder)、磁头号(Head)和扇区号(Sector)。
-
然后,它通过I/O总线,向磁盘控制器的寄存器中写入一连串的命令和参数。
-
发出命令后,驱动程序通常会阻塞等待该请求的进程(使其进入等待状态),并让出CPU。
-
第四层:中断处理程序 (Interrupt Handlers)
-
作用: 当慢速的I/O设备完成其任务时,它需要一种方式来通知CPU。中断就是这个机制。中断处理程序是一段特殊的代码,它在I/O完成后被CPU执行,用于处理I/O完成后的“善后”工作。
-
在本例中的作用:
-
磁盘硬件完成了读取数据块的任务(通常通过DMA直接将数据放入内存的内核缓冲区)。
-
磁盘控制器向CPU发送一个中断信号。
-
CPU立刻暂停当前正在执行的任何任务,跳转到预设的中断服务例程(即中断处理程序)。
-
该程序检查磁盘控制器的状态,确认数据传输成功且无错误。
-
它会唤醒之前因为等待这个I/O而阻塞的进程(将其状态从“等待”改为“就绪”)。
-
处理完毕后,从中断返回,CPU可以继续执行被中断的任务或调度刚被唤醒的进程。
-
第五层:硬件 (Hardware)
-
作用: 物理设备本身,包括设备控制器(芯片)和设备主体(如磁盘盘片、打印机机械结构等)。它负责执行由设备驱动程序发来的电子命令。
-
在本例中的作用:
-
磁盘控制器接收到寄存器中的命令。
-
它驱动磁头臂移动到正确的柱面(寻道),选择正确的磁头。
-
等待磁盘盘片旋转,使目标扇区转到磁头下方(旋转延迟)。
-
读取扇区上的磁信号,转换为数据流,并通过DMA将其直接传输到内存中指定的位置。
-
传输完成后,向CPU发出中断信号。
-
总结一下请求的流程:
用户程序 -> C库 -> 系统调用 -> 设备无关层 -> 设备驱动层 -> 硬件 -> [I/O操作] -> 中断 -> 中断处理层 -> 设备驱动层 -> 设备无关层 -> 返回用户程序