输入/输出设备
概述
I/O 设备
I/O 设备管理是操作系统设计中最凌乱也最具挑战的部分,因为其包含了很多领域的不同设备及其相关应用程序,很难有一个通用且一直的方案。
分类
按照信息交换的单位分类:
- 块设备,以数据块为单位,属于有结构设备,如磁盘等,传输速率较高,可寻址(即可随机地读写任意一块);
- 字符设备,无结构,如交互式终端、打印机等,速率较低,不可寻 址,常使用终端 I/O 方式; 按照速率分类:
- 低速设备,几到几百 ,如键盘鼠标等;
- 中速设备,数千到数万 ,如激光打印机等;
- 高速设备,数百千之千兆 ,如磁盘机和光盘机等。
I/O 接口
I/O 接口是一个 设备控制器,位于 CPU 和设备之间,既要与 CPU 通信,又要与设备通信,还能按照 CPU 发 来的命令控制设备工作。
I/O 接口有单独的数据寄存器和控制/状态寄存器,用于传输数据或存储控制信息和状态信息;一个设备控制器可以连接多个设备,因此有一个或多个设备接口,每个接口中都存在数据、状态和控制三种类型的信号。
I/O 逻辑实现对设备的控制,通过一组控制器与 CPU 交互,将 CPU 的 I/O 命令进行译码。
设备控制器的主要功能有:
- 接受和识别 CPU 的命令,如磁盘控制器能接受读、写、查找等;
- 数据交换,设备和控制器之间、控制器和主存之间的数据传输;
- 表示和报告设备状态;
- 地址识别;
- 数据缓冲;
- 差错控制。
I/O 端口
指的是设备控制器当中可被 CPU 直接访问的 寄存器:
- 数据寄存器,实现 CPU 和外设之间的缓冲;
- 状态寄存器,获取执行结果和设备状态,让 CPU 知道是否准备好;
- 控制寄存器,由 CPU 写入,一边启动命令或更改设备模式;
为了实现 CPU 和 I/O 端口的通信有两种方式:
- 独立编址,为每个端口分配一个 I/O 端口号,所有的 I/O 端口形成 I/O 端口扣减,普通用户程序不能访问,只有操作系统使用特殊的 I/O 指令才能访问;
- 统一编址,有称为 内存映射 I/O,每个端口被分配唯一的内存地址,该地址不会被实际分配给其他内存,通常分配给端口的地址靠近地址空间的顶端;
I/O 控制方式
见 此
I/O 软件层次结构
I/O 软件涉及面很宽,向下与硬件密切相关,向上与虚拟存储器系统、文件系统和用户直接交互;目前普遍采用层次结构设计,煤层利用下层提供的服务:
- 用户 I/O 软件,实现与用户交互的接口,一般大部分都实现在操作系统内部,用户层软件必须通过系统调用获取服务;
- 设备独立性软件,用于实现用户程序和设备驱动器的统一接口、设备命令、设备的保护及设备的分配和释放等,同时为设备管理和数据传送提供必要的存储空间;又称为 设备无关性,使得应用程序独立于具体使用的物理设备;在应用程序中可是使用逻辑设备名来请求某种设备,系统实 际执行时转换为物理设备名;逻辑设备名可以增加设备分配的灵活性,易于实现 I/O 重定向(改变具体设备,而不必改变应用程序);
- 设备驱动程序,与硬件直接相关,负责具体实现对设备发出的操作指令,驱动 I/O 设备工作的驱动程序;通常每类设备配置一个设备驱动程序,是 I/O 进程与设备控制器之间的通信程序,通常以进程的形式存在;向上提供接口,向下和设备控制器通信;可以隐藏 I/O 内核子系统和设备控制器的差异;
- 中断处理程序,保存被中断进程的 CPU 环境,转入相应的中断处理程序,处理完毕后恢复现场,返回被中断进程;中断处理层的重要任务有,进行进程上下文的切换,对处理中断信号源进行测试,读取设备状态和修改进程状态等;
- 硬件
应用程序与 I/O 接口
字符设备接口,以字符为单位、如键盘打印机,传输速率较低,不可寻址,常采用中断驱动方式;
块设备接口,以数据块为单位,如磁盘,传输速率高、可寻址,常采用 DMA 方式;
网络设备接口,网络套接字接口,通过套接字进行连接和发送数据;
阻塞/非阻塞 I/O,调用 I/O 时进程会被阻塞,需要等待 I/O 操作完成;非阻塞就是 I/O 时进程不阻塞,完成后返回错误返回值,通常进程通过轮询方式查询 I/O 是否完成;大多数操作系统都采用阻塞式。
设备独立性软件
总体而言,设备独立性软件包括执行所有设备公有操作的软件;
高速缓存与缓冲区
磁盘高速缓存,利用内存中的一块空间作为缓存,因此逻辑上属于磁盘,物理上是驻留在内存的盘块;有两种形式:
- 开辟单独的空间,大小固定;
- 将未利用的内存空间作为缓冲池,供请求分页系统和磁盘 I/O 时共享。
缓冲区,主要作用:
- 缓和 CPU 和 I/O 设备速度不匹配的矛盾;
- 减少对 CPU 的中断频率,放宽对 CPU 中断响应时间的限制;
- 解决基本数据单元大小不匹配的问题;
- 提高 CPU 和 I/O 设备之间的并行性。 实现方法有:
- 硬件缓冲器,但成本高,一般只用于关键部位;
- 在内存内设置缓冲区:
- 单缓冲,同一时刻只能由一方写入或取出;
- 双缓冲,由于单缓冲存在缓冲区为空之后才能写入,因此使用两个缓冲区,写入和读取分离,提高并行度;此外还能实现双向的数据传输;
- 循环缓冲,由多个大小相等的缓冲区组成,链表组成的环形式;
- 缓冲池,由多个系统中公用的缓冲区组成,分配三个队列,空缓冲队列,输入队列(输入数据已满)和输出队列(输出数据已满)
缓冲区和高速缓存都是介于高速设备和低速设备之间,区别有:
- 高速缓存中的数据在低速设备上也有,而缓冲区不一定;
- 若高速缓存中没有对应数据,则会去低速设备查找,而缓冲区则必须访问,高速设备不会直接访问低速设备;
设备分配和回收
根据用户 I/O 请求分配设备,让设备经可能忙碌,同时避免不合理分配造成死锁,使用三种方式:
- 独占式设备;
- 分时式共享设备;
- 以 SPOOLing 方式使用外部设备,实现了虚拟设备的功能,可以同时将设备分配给多个进程,实质上是实现了对设备 I/O 操作的批处理。
设备分配的主要数据结构有:
- 设备控制表(DCT),一个设备控制表表示一个设备,表现是设备的属性,申请设备的进程 PCB 会排成一个设备队列;
- 控制器控制表(COCT),控制设备与内存交换数据,而设备控制器又要请求通道为它服务,每个 COCT 都有一个表相指向相应的通道控制表指针;
- 通道控制表(CHCT),一个通道可以为多个设备控制器服务,因此 COCT 中还有指向这些设备控制器表的指针;CHCT 与 COCT 的关系是一对多的关系;
- 系统设备表(SDT),整个系统只有一张 SDT,记录所有已连接的设备。
设备分配有静态和动态,前者主要用于独占式设备的分配,在作业开始前,系统一次性分配需要的所有设备、控制器,不会出现死锁但利用率低;后者在进程执行过程中,按需分配。
安全分配方式:阻塞式,阻塞过程中也不保持任何资源,但 CPU 和 I/O 串行工作;
不安全分配方式,非阻塞式,仅当所需设备被占用才阻塞,一个进程可操作多个设备,推进迅速,但可能造成死锁。
逻辑设备名到物理设备名的映射:提高设备分配的灵活性和利用率,方便实现 I/O 重定向,引入了设备独立性。系统中有一张 逻辑设备表(Logical Unit Table, LUT),表项包括逻辑设备名、物理设备名和设备驱动程序入口地址;一般可以为整个系统或是每个用户设立一张 LUT。
SPOOLing 技术(假脱机技术)
将独占设备改造称共享设备的技术,利用专门的外围控制器,将低速 I/O 设备上的数据传送到高速磁盘,或者相反。
输入井和输出井,在磁盘中,模拟脱机输入/出时的磁盘,分别接收 I/O 和用户程序的输入/出;一个进程的输入/输出保存为一个文件,所有进程的文件连接为一个队列。
输入/输出缓冲区,在内存中,连接输入/输出 设备和输入/输出井;
实际上就是 I/O 设备将输入存入缓冲区,或者进程将输出存储缓冲区,等到其设备空闲时再从缓冲区中获取数据。
设备驱动程序接口
要求每个驱动程序与操作系统之间有相同或相近的接口,方便添加新设备驱动程序。对于每种设备类型,例如磁盘,操作系统都要定义一组驱动程序必须支持的函数,对磁盘而言,必须包含读、写、格式化等,驱动程序中常包含一张表,