跳至主要內容

Chapter5 IO

Chiichen原创大约 9 分钟课程笔记操作系统

I/O 硬件

I/O 设备

  • 块设备:把信息存储在定长的块中,每个块都有自己的地址。块的大小从 512B 到 32KB 不等。可以独立读写每个块。例如:硬盘,U 盘等
  • 字符设备:发送或者接收一个字符序列,不可寻址,也没有 seek 操作。例如:打印机、网卡、鼠标等。

设备控制器

  • 有的是集成在主板上,有的是从外部插入的。例如 PCIe 插槽中的插入部件。通常就是设备控制器(controller)或者叫做设备适配器(adapter)
io硬件控制器.png
io硬件控制器.png
  • 作用是:
    1. 把串行的二进制 01 流转化成字节块
    2. 执行可能的错误处理
    3. 与内存交互
io控制器2.png
io控制器2.png
  • 每个控制器都会有一些寄存器来与 CPU 通信,操作系统可以通过写入这些寄存器来和外部设备通信,也可以通过读取这些寄存器来获取设备的状态信息。

  • 引出了问题,怎么对这些控制器寄存器进行寻址,以及怎么在控制器和内存之间传输数据。

  • 方法:

    1. 独立的 I/O 和内存空间
    2. 内存映射 I/O
    3. 混合方案。

I/O 寻址方案

独立的 I/O 和内存空间

  • 每个控制器寄存器都被分配了一个特殊的地址,被称为 I/O port number。一些特殊的 I/O 指令被用来向这些控制器寄存器中进行读/写。例如INREG,PORTOUTREG,PORT分别进行写入和读取
  • 要注意INR0,4MOVR0,4在这种情况下是有不同的语义的,前者的 4 代表的是在控制器寄存器中地址为 4,后者的 4 代表的是在主存中地址为 4。

内存映射 I/O

  • 把内存地址空间中的一部分作为控制器寄存器的地址空间
优缺点
  • 优点:

    1. 不需要特殊的指令来进行对控制寄存器的读写操作
    2. 不需要特殊的保护机制来保护控制寄存器不被用户直接访问
    3. 每个指令既可以引用内存,也可以引用控制寄存器
  • 缺点:

    1. 如果设备控制器寄存器的值是缓存,这就会出现问题,我们不想要读取缓存的软拷贝值,我们想要的是寄存器的值。解决方法是禁用对应控制寄存器的那部分虚页的缓存功能
    2. 由于只有一个地址空间,需要检查每个内存的引用来确定是要主存响应还是要 IO 设备响应。
  • 对总线有要求
    内存映射IO的总线.png

混合实现

  • 数据寄存器使用内存映射的地址空间
  • 控制寄存器使用独立的地址空间
三种IO设备地址空间的实现方法.png
三种IO设备地址空间的实现方法.png

I/O 软件

简介

  • 设备独立性:程序可以访问任何 IO 设备,不需要提前指定设备
  • 通用命名:命名不依赖机器
  • 错误处理
  • 同步 vs 异步:阻塞传输 vs 中断驱动
  • 缓冲
  • 可共享的设备 vs 专用的设备:例如硬盘是可共享的,磁带驱动器不是。

I/O 实现

程序控制的 I/O(Programmed I/O)

  • 在 IO 完成前,CPU 一直处于 busy 状态
  • 在单进程系统中没问题,但是在多道程序系统和分时系统中就不行了,因为 IO 很消耗时间。
  • 以打印机打印“ABCD”为例
程序控制的io.png
程序控制的io.png
/*buffer is user buffer
p is kernel buffer
count is number of bytes to be copied
*/
copy_from_USer(buffer, p,couunt);
for (i = 0;i< count;i++){
    while (*printer status reg != READY);
    *printer_data_register=p[i];
}
return_to_user();
  • CPU 会不断轮询打印机寄存器的状态,知道所有字符串打印完毕,这大大浪费了其他的 CPU 时间

中断驱动的 I/O(Interrupt-Driven I/O)

中断示意图.png
中断示意图.png
  • 同样以打印机打印"ABCD"为例

  • 每次打印完发出一个中断,再接着进行下一次打印
    中断驱动的IO.png

  • 缺点是每个字符打印都会产生中断,而 CPU 要响应每个中断十分耗时

DMA(直接内存访问)

  • 因此在 DMA 中,DMA 控制器会把字符从内核缓冲区直接“喂”给打印机控制器,CPU 就不用直接响应这个中断了。直到整个缓冲区内的字符都被传输完了,CPU 被中断抢占。
    DMA控制的IO2.png
    DMA控制的IO1.png

I/O 软件层次结构

io软件层次.png
io软件层次.png
  • 最顶层是用户空间,中间三层是内核空间,最底层是硬件。

I/O 处理器(Handler)

  • 最好把 I/O 处理的过程隐藏起来,因此中断处理通常由引起中断的上层进行(Interrupt Handler)

中断处理过程

  • 中断向量就是中断服务程序的首地址
软件处理过程
  1. 保存没有被中断硬件存储的寄存器的值
  2. 设置中断服务程序的上下文
  3. 设置中断服务程序的栈
  4. 响应中断控制器,重新开启中断
  5. 将寄存器从保存位置复制到进程表
  6. 运行服务程序
  7. 选择下一个要进行的进程
  8. 设置 MMU 上下文为下一个要运行的进程
  9. 加载新进程的寄存器
  10. 开始运行新进程

设备驱动程序(Device Drivers)

  • 把一个与设备无关的 I/O 请求对应到一个具体的硬件设备上
  • 通常是由设备厂商编写
  • 操作系统通常会定义一个接口来规范所有驱动程序
  • 操作系统通常会把驱动分成块设备驱动和字符设备驱动

设备驱动程序功能

  • 从上层接受一个抽象的读写请求,与设备无关的请求,传化为一个与设备有关的具体的请求。例如从操作系统中接收一个访问某个块号的请求,转化为具体的磁道、扇区。
  • 初始化设备
  • 检查该设备是否被其他请求使用,利用队列管理请求
  • 可以向设备发送命令控制设备
  • 检查设备错误信息

设备统一接口

统一接口.png
统一接口.png

主设备号与次设备号

  • 主设备号(Major number)用来定位驱动程序,次设备号(Minior number)用来定位这个驱动程序控制下的某个具体设备
    主次设备号.png

Buffer

io缓存.png
io缓存.png

错误处理

  • 有一些错误可以在底层设备处理,例如一些校验和错误,通过随机 bit 尝试修复 block
  • 底层设备处理不了的话就传到上层设备驱动程序处理,例如无法读取 block 的时候重新读取
  • 再无法处理的错误就传到 OS 的设备无关软件层处理,例如尝试向只读设备中写入数据

设备无关的块大小

  • 不论具体设备的块大小(例如不同磁盘有不同的扇区大小),对于文件系统来说都是固定的块大小

用户空间 I/O 软件

  • I/O 库提供 I/O 函数来给用户提供对应的 I/O 系统调用的实现,还提供例如格式化的 I/O 的操作(printf())
  • 有些应用程序不直接写入 IO 设备,而是写入假脱机文件(spooler)

硬盘

硬盘结构

  • 被分成柱面(cylinders),每个柱面包含磁道(tracks),每个磁道被分成了一些扇区(sectors),扇区大小通常为 512bytes
    硬盘结构.png
  • 物理上的硬盘随着半径的增长,扇区的数量可能会增加,因此硬盘给操作系统提供了图二的结构抽象,使得每个磁道上都有固定数量的扇区

硬盘格式

  • 硬盘生产完时是没有任何数据的,要进行格式化,而格式也包括低级格式(如下图所示)和高级格式
扇区格式.png
扇区格式.png

柱面斜进(cylinder skew)

柱面斜进.png
柱面斜进.png
  • 就是为了补偿寻道过程中盘片的旋转时间
  • 例如:10000rpm(6ms/圈),一个磁道有 300 个扇区(20μs/sector),寻道时间为 800μs,那么就要斜进 40 个扇区。

交错(interleaving)

  • 从硬盘控制器的缓冲区把数据复制到内存中需要时间,这就会导致在连续读取的时候有可能磁头就“过站”了,再访问下一个连续的扇区反而要多转一圈,因此通过交错的方法,使得访问的下一个逻辑扇区不是下一个物理扇区,也就是提高两个扇区之间的时间间隔。
    扇区交错.png

硬盘表现的度量

  • 访问时间(access time):从读写请求到达到数据传输开始的时间
  • 寻道时间(seek time):从当前磁道移动到指定磁道的时间,平均有一半的寻道时间是最差情况(一般是 4-10ms)。
  • 旋转延迟(Rotational Latency):扇区从要被访问到出现在磁头下的时间,平均有一半是最差情况,一般的硬盘要花费 4-11ms
  • 数据传输速率(data-transfer rate):从硬盘读写数据的速度
  • 平均无故障时间(Mean time to failure ,MTTF):平均无故障连续运行的时间。(通常 3-5 年)

磁盘臂调度算法(Disk Arm Scheduling Algorithms)

先到先服务(FCFS)

  • 就是先到的先处理。

最短寻道时间(Shortest Seek First, SSF)

  • 先服务寻道时间最短的,但是这种方法可能导致饥饿的情况
    SSF.png

电梯算法(Elevator algorithm)

  • 让磁盘臂沿一个方向运行,直到那个方向没有别的请求了,再回头,还可以变式成在完成最高编号的柱面后,移动到编号最小的柱面再向上移动(也就是把最小编号看成最大编号的相邻柱面),这样有更好的响应时间。
  • 好处是给定一组请求,磁盘臂移动的次数的上界永远是柱面数的两倍。
    电梯算法.png

错误处理

  • 预留扇区来给坏扇区使用,当检测到有扇区损坏的时候,就把预留扇区映射到原来的坏扇区中。
    扇区错误处理.png