I/O硬件
总线(Bus)与I/O系统结构
总线
总线带宽 $W_{\text{Bus}}$ 可由下式给出:
\[W_{\text{Bus}}=f\times w\qquad(\mathrm{Bytes/Second})\]其中, $f$ 为总线频率, $w$ 为总线宽度.
I/O系统结构
不同的 I/O 设备, 其传输速率可能相差 12 个数量级.
I/O设备与管理
I/O设备分类
- 按类型分类:
- 传输速度: 低速设备, 中速设备, 高速设备.
- 信息交换: 块设备, 字符设备.
- 共享属性: 独占设备, 共享设备, 虚拟设备.
- 按接口分类:
- 数据信号
- 控制信号
- 状态信号
设备管理
- 目标:
- 提高效率: 匹配高速CPU与低速外设.
- 方便使用: 为用户访问不同类别的外设提供统一接口, 协调外设的并发.
- 方便控制: 方便OS内部对设备的控制.
- 功能:
- 提供设备使用的用户接口: 命令接口和编程接口.
- 设备分配与释放: 使用设备前, 分配设备与相应的通道, 控制器.
- 设备访问与控制: 并发访问与差错处理.
- I/O缓冲与调度: 提高访问效率.
设备控制器
功能:
- 接受和识别CPU命令
- 在CPU与控制器, 控制器与设备之间做数据交换
- 了解与报告设备状态
- 识别设备地址
- 作为缓冲区
- 对设备传来的数据进行差错控制
组成:
- 控制器与CPU的接口: 数据寄存器, 控制寄存器, 状态寄存器.
- 控制器与设备的接口.
- I/O逻辑: 提供了CPU对I/O设备的控制.
I/O软件
常见的I/O控制方式有如下四种:
- 程序控制I/O, 也称轮询或查询方式I/O, 由CPU代表进程向I/O模块发出指令, 然后进入忙等状态, 直到操作完成后, 进程才能继续执行.
- 中断驱动, 当I/O操作结束后由设备控制器主动通知设备驱动程序, 而不是设备驱动程序轮询.
- 直接存储访问(DMA), 由一个专门的控制器来完成数据从内存到设备或从设备到内存的传输工作.
- 通道(Channel), 原理与DMA几乎一样. 通道是具有特殊功能的处理器, 有自己的指令集与程序来专门负责数据的输入输出控制. CPU将传输数据的工作下放给通道, 而CPU本身只负责数据处理. 这样CPU与通道这两个处理器就可以并行工作.
程序控制I/O
CPU 利用率相当低, 外设进行数据处理时, CPU 只能轮询等待.
中断驱动
提高了 CPU 的利用率, 但是每次访问设备都需要发送中断, 只适用于数据传输量较低的设备.
直接存储访问(DMA)
一次中断可读写一批数据, 适用于高速设备.
但是, 数据传输的方向, 存储数据的内存地址, 传送数据的长度等都由 CPU 控制, 占用 CPU 时间. 且每一个设备都需要占用一个 DMA 控制器, 当设备增加时, 需要增加新的 DMA 控制器.
通道(Channel)
I/O通道是专门负责输入输出的处理器, 独立于CPU, 由自己的指令集. 可以执行由通道指令组成的通道程序, 因此可以进行较为复杂的I/O控制. 通道程序通常由操作系统构造, 存在于内存中.
执行一个通道程序可以完成几组 I/O 操作, 相比于 DMA 更进一步地减少了 CPU 的干预. 但是通道技术的费用较高.
缓冲技术
缓冲技术可以提高外设利用率:
- 匹配高速的CPU与低速的外设
- 减少CPU的中断次数
- 提高CPU和I/O设备之间的并行性
- 单缓冲(Single Buffer): 一个内核缓冲区, CPU与外设轮流使用.
- 双缓冲(Double Buffer): 两个内核缓冲区, CPU与外设可以连续处理, 无需互相等待. 但是要求CPU与外设的速度相近.
- 环形缓冲(Circular Buffer): 多个内核缓冲区, CPU与外设的处理速度可以相差较大.
- 缓冲池(Buffer Pool): 整体利用率较高.
缓冲技术的问题: 多次复制同一个数据包.
设备分配
由于外设资源有限, 需要解决进程间的外设共享问题, 以提高外设资源的利用率. 设备分配就是对进程使用外设过程的管理. 其基本做法有以下两种:
- 在进程间切换, 轮流使用外设;
- 使用一个虚拟设备将外设与应用进程分隔开, 只有虚拟设备(软件)才能使用外设.
设备分配时需要考虑的因素:
- 设备固有属性: 独享, 共享, 虚拟
- 设备分配算法: 先来先服务, 优先级
- 设备分配安全 - 死锁问题
- 安全分配(同步): 在设备分配中防止死锁, 进程发出 I/O 请求之后, 进入阻塞, 直到 I/O 完成.
- 不安全分配(异步): 设备在分配时不考虑可能产生的死锁, 进程发出 I/O 请求后, 仍能继续执行, 可继续请求其他设备. 需要进行安全检查, 否则可能导致死锁.
- 设备独立性:
- 用户程序的设备独立性: 用户程序使用逻辑设备名, 系统实际执行时, 需要映射到实际设备名.
- I/O 软件的设备独立性: 除了直接和设备打交道的底层软件外, 其余部分的软件不依赖于设备, 可提高设备管理软件的效率.
单通路I/O系统的设备分配
单通路是指一个设备对应一个控制器, 一个控制器对应一个通道.
- 分配设备: 根据物理设备名查找系统设备表(System Device Table, SDT), 从中找到对应的设备控制器表(Device Control Table, DCT). 若设备正忙, 则进入其等待队列; 否则, 计算是否产生死锁, 若产生死锁, 则放弃这次分配, 否则进行分配.
- 分配设备控制器: 将设备分配给进程后, 在设备控制器表(DCT)中找到该设备相连的控制器控制表(COntroller Control Table, COCT), 若控制器正忙, 则进入其等待队列; 否则分配.
- 分配通道: 从控制器控制表(COCT)中找到相连的通道控制表(Channel Control Table, CHCT), 若通道正忙, 则进入其等待队列; 否则分配.
多通道I/O系统的设备分配
多通道是指一个设备与若干个控制器相连, 一个控制器与若干个通道相连. 其分配过程与单通道的相似.
假脱机技术(SPOOLing)
SPOOL: Simultaneous Peripheral Operation On Line
假脱机技术: 将独享设备转变为具有共享特征的虚拟设备. 利用一个专门的SPOOLing程序来完成对设备的I/O操作, 其他程序访问该程序即可.
- 实际I/O:
- SPOOLing程序预先从外设输入数据并加以缓冲, 在以后需要时输入到应用程序.
- SPOOLing程序接受应用程序的输出数据并加以缓冲, 在适当的时候输出到外设.
- 虚拟I/O:
- 应用程序进行I/O操作时, 只是和SPOOLing程序交换数据, 并不是与实际外设进行I/O操作.
SPOOLing技术有如下特点:
- 高速虚拟I/O: 应用程序的虚拟I/O比实际I/O速度提高, 缩短了应用程序的执行时间. 另一方面, 程序的虚拟I/O操作时间与实际I/O操作时间分离.
- 实现对独享设备的共享: 由SPOOLing程序提供虚拟设备, 可以对独享设备依次(互斥)共享使用.
设备驱动(Driver)
设备驱动的主要功能:
- 将抽象的I/O请求转化为对物理设备的请求.
- 检查I/O请求的合法性.
- 初始化设备.
- 启动设备.
- 发出I/O命令.
- 响应中断请求.
- 构造通道程序.
其组成部分有:
- 自动配置和初始化子程序: 检测所要驱动的硬件是否存在且正常. 若该设备正常, 则对该设备及其相关的设备驱动程序需要的软件状态进行初始化, 则对该设备及其相关的设备驱动程序需要的软件状态进行初始化. 在初始化时调用一次.
- 服务于I/O请求的子程序: 调用该子程序是系统调用的结果. 执行该部分程序时, 系统仍认为是和调用进程属于同一进程, 只是由用户态陷入了内核态, 具有进行此系统调用的用户程序的运行环境, 可在其中调用
SLEEP
等与进程运行环境相关的函数. - 中断服务子程序: 系统接收硬件中断, 再由系统调用中断服务子程序. 因为设备驱动程序一般支持同一类型的若干设备, 所以一般在系统调用中断服务子程序的时候, 都带有一个或多个参数, 以唯一标识请求服务的设备.
设备驱动的共性:
- 核心代码: 设备驱动是内核的一部分, 出错将导致系统 PANIC.
- 核心接口: 设备驱动必须作为内核提供的一个标准接口. 例如终端驱动为内核提供的一个文件 I/O 接口.
- 核心机制与服务: 可以使用标准的内核服务如内存分配, 中断发送和等待队列等.
- 动态可加载: 在内核模块发出加载请求时加载; 在不再使用时卸载, 内核能有效地利用系统资源.
- 动态性: 系统启动及设备驱动初始化时将查找它所控制的硬件设备. 若某个设备的驱动为一个空过程时, 不会对系统造成危害, 只是会占用少量系统内存.