第五章 设备管理-5.1 IO管理概述
5.1 I/O管理概述
1. IO设备的概念和分类
1.1 什么是I/O设备?
"I/O"就是"输入/输出"(Input/Output)
I/O设备就是可以将数据输入到计算机, 或者可以接收计算机输出数据的外部设备, 属于计算机中的硬件部件
- 鼠标、键盘 -- 典型的输入型设备
- 显示器 -- 输出型设备
- 移动硬盘 -- 既可输入、又可输出的设备
UNIX系统将外部设备抽象为一种特殊的文件, 用户可以使用与文件系统相同的方式对外部设备进行操作
- Write操作: 向外部设备写出数据
- Read操作: 从外部设备读入数据
1.2 I/O设备的分类
- 按使用特性分类
- 人机交互类外部设备: 数据传输速度慢
- 鼠标、键盘、打印机等 -- 用于人机交互
- 存储设备: 数据传输速度快
- 移动硬盘、光盘等 -- 用于数据存储
- 网络通信设备: 数据传输速度介于上述二者之间
- 调制解调器等 -- 用于网络通信
- 人机交互类外部设备: 数据传输速度慢
- 按传输速率分类
- 低速设备
- 鼠标、键盘等 -- 传输速率为每秒几个到几百字节
- 中速设备
- 激光打印机等 -- 传输速率为每秒数千至上万个字节
- 高速设备
- 磁盘等 -- 传输速率为每秒数千字节至千兆字节的设备
- 低速设备
- 按信息交换的单位分类
- 块设备: 传输速率较高, 可寻址,
即对它可随机地读/写任一块
- 磁盘等 -- 数据传输的基本单位是"块"
- 字符设备: 传输速率较慢, 不可寻址,
在输入/输出时常采用中断驱动方式
- 鼠标、键盘等 -- 数据传输的基本单位是字符
- 中断驱动方式: 一种I/O控制方式
- 块设备: 传输速率较高, 可寻址,
即对它可随机地读/写任一块
2. IO控制器
2.1 I/O设备的组成
- 机械部件
- I/O设备的机械部件主要用来执行具体I/O操作
- 如我们看得见摸得着的鼠标/键盘的按钮; 显示器的LED屏; 移动硬盘的磁臂、磁盘盘面
- 电子部件(I/O控制器, 又称设备控制器)
- I/O设备的电子部件通常是一块插入主板扩充槽的印刷电路板
2.2 I/O控制器的主要功能
CPU无法直接控制I/O设备的机械部件, 因此I/O设备还要有一个电子部件作为CPU和I/O设备部件之间的"中介", 用于实现CPU对设备的控制
这个电子部件就是I/O控制器, CPU可控制I/O控制器, 又由I/O控制器来控制设备的机械部件
主要功能:
- 接受和识别CPU发出的命令
- 如CPU发来的read/write命令, I/O控制器中会有相应的控制寄存器来存放命令和参数
- 向CPU报告设备的状态
- I/O控制器中会有相应的状态寄存器用于记录I/O设备的当前状态
- 如: 1表示空闲, 0表示忙碌
- 数据交换
- I/O控制器中会设置相应的数据寄存器。输出时, 数据寄存器用于暂存CPU发来的数据, 之后再由控制器传送设备; 输入时, 数据寄存器用于暂存设备发来的数据, 之后CPU从数据寄存器中取走数据
- 地址识别
- 类似于内存的地址, 为了区分设备控制器中的各个寄存器, 也需要给各个寄存器设置一个特定的"地址"。I/O控制器通过CPU提供的"地址"来判断CPU要读/写的是哪个寄存器
- 接受和识别CPU发出的命令
2.3 I/O控制器的组成
- 值得注意的小细节:
- 一个I/O控制器可能会对应多个设备
- 数据寄存器、控制寄存器、状态寄存器可能有多个(如: 每个控制/状态寄存器对应一个具体的设备), 且这些寄存器都要有相应的地址, 才能方便CPU操作。有的计算机会让这些寄存器占用内存地址的一部分, 称为内存映像I/O; 另一些计算机则采用I/O专用地址, 即寄存器独立编址
2.4 两种寄存器编址方式
3. IO控制方式
- 需要注意的问题:
- 完成一次读/写操作的流程
- CPU干预的频率
- 数据传送的单位
- 数据的流向
- 主要缺点和主要优点
3.1 程序直接控制方式
完成一次读/写操作的流程(以读操作为例):
CPU通过控制线向控制器发出读指令, 于是设备启动, 并且状态寄存器设为1(未就绪)
轮询检查控制器的状态(其实就是在不断地执行程序的循环, 若状态位一直是1, 说明设备还没准备好要输入的数据, 于是CPU会不断地轮询)
输入设备准备好数据后将数据传给控制器, 并报告自身状态
控制器将输入的数据放到数据寄存器中, 并将状态改为0(已就绪)
CPU发现设备已就绪, 即可将数据寄存器中的内容读入CPU的寄存器中, 再把CPU寄存器中的内容放入内存
若还要继续读入数据, 则CPU继续发出读指令
CPU干预的频率
- 很频繁, I/O操作开始之前、完成之后需要CPU的介入, 并且在等待I/O完成的过程中CPU需要不断地轮询检查
数据传送的单元
- 每次读/写一个字
数据的流向
读操作(数据输入): I/O设备 → CPU(指的是CPU的寄存器) → 内存
写操作(数据输出): 内存 → CPU → I/O设备
每个字的读/写都需要CPU的帮助
主要缺点和主要优点
优点: 实现简单。在读/写指令之后, 加上实现循环检查的一系列指令即可(因此才称为"程序直接控制方式")
缺点: CPU和I/O设备只能串行工作, CPU需要一直轮询检查, 长期处于"忙等"状态, CPU利用率低
3.2 中断驱动方式
完成一次读/写操作的流程(以读操作为例):
引入中断机制。由于I/O设备速度很慢, 因此在CPU发出读/写命令后, 可将等待I/O的进程阻塞, 先切换到别的进程执行
当I/O完成后, 控制器会向CPU发出一个中断信号, CPU检测到中断信号后, 会保存当前进程的运行环境信息, 转去执行中断处理程序处理该中断
处理中断的过程中, CPU从I/O控制器读一个字的数据传送到CPU寄存器, 再写入主存
接着, CPU恢复等待I/O的进程(或其他进程)的运行环境, 然后继续执行
注意:
CPU会在每个指令周期的末尾检查中断
中断处理过程中需要保存、恢复进程的运行环境, 这个过程是需要一定时间开销的。可见, 如果中断发生的频率太高, 也会降低系统性能
CPU干预的频率
每次I/O操作开始之前、完成之后需要CPU的介入
等待I/O完成的过程中CPU可以切换到别的进程执行
数据传送的单元
- 每次读/写一个字
数据的流向
读操作(数据输入): I/O设备 → CPU(指的是CPU的寄存器) → 内存
写操作(数据输出): 内存 → CPU → I/O设备
主要缺点和主要优点
优点: 与"程序直接控制方式"相比, 在"中断驱动方式"中, I/O控制器会通过中断信号主动报告I/O已完成, CPU不再需要不停地轮询。CPU和I/O设备可并行工作, CPU利用率得到明显提升
缺点: 每个字在I/O设备与内存之间的传输, 都需要经过CPU, 而频繁的中断处理会消耗较多的CPU时间
3.3 DMA方式(Direct Memory Access, 直接存储器存取)
完成一次读/写操作的流程(以读操作为例):
与"中断驱动方式相比", DMA方式(主要用于块设备的I/O控制)有这样几个改进:
数据的传送单位是"块", 不再是一个字、一个字的传送
数据的流向是从设备直接放入内存, 或者从内存直接到设备, 不再需要CPU作为"快递小哥"
仅在传送一个或多个数据块的开始和结束时, 才需要CPU干预
CPU干预的频率
- 仅在传送一个或多个数据块的开始和结束时, 才需要CPU干预
数据传送的单元
每次读/写一个或多个块
- 注意: 每次读写的只能是连续的多个块, 且这些块读入内存后在内存中也必须是连续的
数据的流向(不再需要经过CPU)
读操作(数据输入): I/O设备 → 内存
写操作(数据输出): 内存 → I/O设备
主要缺点和主要优点
优点: 数据传输以"块"为单位, CPU介入频率进一步降低。数据的传输不再需要先经过CPU再写入内存, 数据传输效率进一步增加, CPU和I/O设备的并行性得到提升
缺点: CPU每发出一条I/O指令, 只能读/写一个或多个连续的数据块。如果要读/写多个离散存储的数据块, 或者要将数据分别写到不同的内存区域时, CPU要分别发出多条I/O指令, 进行多次中断处理才能完成
3.4 通道控制方式
- 通道: 一种硬件, 可以理解为是"弱鸡版的CPU",
通道可以识别并执行一系列通道指令
与CPU相比, 通道可以执行的指令很单一, 并且通道程序是放在主机内存中的, 也就是说通道与CPU共享内存
一个通道可以控制多个I/O控制器, 一个I/O控制器可以控制多个I/O设备
- 完成一次读/写操作的流程(以读操作为例):
- CPU干预的频率
- 极低, 通道会根据CPU的指示执行相应的通道程序, 只有完成一组数据库的读/写后才需要发出中断信号, 请求CPU干预
- 数据传送的单元
- 每次读/写一组数据块
- 数据的流向(在通道的控制下进行)
- 读操作(数据输入): I/O设备 → 内存
- 写操作(数据输出): 内存 → I/O设备
- 主要缺点和主要优点
- 优点: CPU、通道、I/O设备可并行工作, 资源利用率很高
- 缺点: 实现复杂, 需要专门的通道硬件支持
4. IO软件层次结构
4.1 用户层软件
用户层软件实现了与用户交互的接口, 用户可直接使用该层提供的、与I/O操作相关的库函数对设备进行操作
- Eg: printf("hello, world!");
用户层软件将用户请求翻译成格式化的I/O请求, 并通过"系统调用"请求操作系统内核的服务
- Eg: printf("hello world!"); 会被翻译成等价的write系统调用, 当然, 用户层软件也会在系统调用时填入相应参数
Windows操作系统向外提供了一系列系统调用, 但是由于系统调用的格式严格, 使用麻烦, 因此在用户层上封装了一系列更方便的库函数接口供用户使用(WIndows API)
4.2 设备独立性软件(设备无关性软件)
与设备的硬件特性无关的功能几乎都在这一层实现
主要实现功能:
- 向上层提供统一的调用接口(如 read/write 系统调用)
- 设备的保护
- 原理类似于文件保护, 设备被看做是一种特殊的文件, 不同用户对各个文件的访问权限是不一样的, 同理, 对设备的访问权限也不一样
- 差错处理
- 设备独立性软件需要对一些设备的错误进行处理
- 设备的分配与回收
- 数据缓冲区管理
- 可以通过缓冲技术屏蔽设备之间数据交换单位大小和传输速度的差异
- 建立逻辑设备名到物理设备名的映射关系;
根据设备类型选择调用相应的驱动程序
- 用户或用户层软件发出I/O操作相关的系统调用时,
需要指明这次要操作的I/O设备的逻辑设备名
- Eg: 去学校打印店打印时, 需要选择打印机1/打印机2/打印机3, 其实这些都是逻辑设备名
- 设备独立性软件需要通过"逻辑设备表(LUT, Logical Unit Table)"来确定逻辑设备对应的物理设备, 并找到该设备对应的设备驱动程序
- 操作系统可以采用两种方式管理逻辑设备表(LUT):
- 第一种方式, 整个系统只设置一张LUT, 这就意味着所有用户不能使用相同的逻辑设备名,因此这种方式只适用于单用户操作系统
- 第二种方式, 为每个用户设置一张LUT, 各个用户使用的逻辑设备名可以重复, 适用于多用户操作系统, 系统会在用户登录时为其建立一个用户管理进程, 而LUT就存放在用户管理进程的PCB中
- 为什么不同类型的I/O设备需要有不同的驱动程序处理?
- 各式各样的设备, 外形不同, 其内部的电子部件(I/O控制器)也有可能不同
- 如状态寄存器判断是否忙碌的标志位不同, 有的设备用1表示忙碌, 而有的用0表示忙碌
- 不同设备的内部硬件特性也不同, 这些特性只有厂家才知道, 因此厂家须提供与设备相对应的驱动程序, CPU执行驱动程序的指令序列, 来完成设置设备寄存器、检查设备状态等工作
- 各式各样的设备, 外形不同, 其内部的电子部件(I/O控制器)也有可能不同
- 用户或用户层软件发出I/O操作相关的系统调用时,
需要指明这次要操作的I/O设备的逻辑设备名
4.3 设备驱动程序
- 主要负责对硬件设备的具体控制,
将上层发出的一系列命令(如
read/write)转化为特定设备"能听得懂"的一系列操作,
包括设置设备寄存器、检查设备状态等
- 注: 驱动程序一般会以一个独立进程的方式存在
4.4 中断处理程序
当I/O任务完成时, I/O控制器会发送一个中断信号, 系统会根据中断信号类型找到相应的中断处理程序并执行
中断处理程序的处理流程如下:
- 可见, 中断处理程序也会和硬件直接打交道
5. 输入/输出应用程序接口&驱动程序接口
5.1 输入/输出应用程序接口
- 网络设备接口示例:
5.2 阻塞/非阻塞 I/O
- 阻塞I/O: 应用程序发出I/O系统调用,
进程需转为阻塞态等待
- Eg: 字符设备接口 -- 从键盘读一个字符(get系统调用)
- 非阻塞I/O: 应用程序发出I/O系统调用,
系统调用可迅速返回, 进程无需阻塞等待
- Eg: 块设备接口 -- 往磁盘写数据(write系统调用)
5.3 设备驱动程序接口
若各公司开发的设备驱动程序接口不统一, 则操作系统很难调用设备驱动程序
统一标准的设备驱动程序接口
- 操作系统规定好设备驱动程序的接口标准, 各厂商按要求开发设备驱动程序
- 不同的操作系统, 对设备驱动程序接口的标准各不相同, 设备厂商必须根据操作系统的接口要求,开发相应的设备驱动程序, 设备才能被使用