输入输出管理
I/O控制器
作为CPU和I/O设备的中介,用于实现CPU对设备的控制。
功能
- 接受和识别CPU发出的命令(read/write命令,通过控制寄存器存放命令和参数)
- 向CPU报告设备的状态,通过状态寄存器记录设备当前状态
- 数据交换,设置数据寄存器
- 地址识别
组成
- CPU与控制器的接口,包括数据、控制、状态寄存器
- I/O逻辑,负责接收、识别,对设备发送各种命令
- 控制器和设备的接口,实现控制器与设备之间的(数据、状态、控制)通信
一个I/O控制器可能会对应多个设备
数据、状态、控制寄存器可能有多个,且每个寄存器都占有内存地址的一部分,称为内存映像I/O,另一些计算机采用I/O专用地址,即寄存器独立编址
I/O控制方式
程序直接控制方式
- CPU向控制器发出读指令,启动设备,状态寄存器设为1(忙)
- 在等待输入设备的过程中,CPU轮询检查控制器状态,若为1,则说明设备未就绪
- 输入设备准备完毕,将数据传给控制器,报告自身状态
- 控制器将输入的数据放到数据寄存器中,将状态改为0(就绪)
- CPU轮询结束,将数据读到自身的寄存器中,再存入内存
CPU干预频率很频繁,每次读一个字
- CPU和I/O设备只能串行工作,CPU长期处于忙等,利用率低
中断驱动方式
引入中断机制
- 在CPU发出读/写命令后,将等待I/O的进程阻塞,切换并执行其他进程
- I/O完成后,控制器发出中断信号
- CPU检测到中断信号,保存当前运行程序环境信息,执行中断处理程序
- CPU从I/O设备读取一个字的数据到CPU寄存器,写入主存
- CPU恢复等待进程的I/O进程的运行环境,继续执行
CPU每次在指令周期末检查中断
中断处理过程中需要保存、恢复进程的运行环境,需要一定的时间开销
每次读/写一个字,CPU利用率较程序直接控制方式高,CPU和I/O可并行工作
DMA方式
- 主要用于块设备,因为每次读写的单位是块
- 数据的流向从设备直接放入内存,或内存直接到设备
- 仅在传送一个或多个数据块的开始和结束时,才需要CPU干预
CPU大部分的任务被DMA控制器接管
- 通过数据寄存器DR暂存设备到内存,内存到设备的数据
- 内存地址寄存器MAR存放内存地址,表明数据存/出的位置
- 通过数据寄存器DC,表示剩余读写的字节数
- 通过命令/状态寄存器存放CPU发来的I/O命令,或设备的状态信息
CPU每发出一条I/O指令,只能读/写一个或多个连续的数据块
所以数据块要离散地存放,只能通过CPU发出多次中断进行存放
通道控制方式
为了解决数据块离散存储的问题,提出一种叫通道的硬件,可以识别一系列通道指令
-
CPU向通道发出I/O指令,指明通道程序(任务清单)在内存中的位置,并指明要操作的是哪个I/O设备,之后CPU就切换到其他进程执行
-
通道执行内存中的通道程序(其指明了要读入/写出多少数据),读/写的数据应放在内存的什么位置)
CPU干预频率:只在完成一组数据块的读和写后才发出中断信号,请求CPU干预
- CPU、通道、I/O设备可并行工作
I/O软件层次结构
其中,中间三层属于操作系统的内核部分,即I/O系统,或称I/O核心子系统
用户层软件
实现与用户交互接口,用户可直接使用I/O相关的库函数操作设备
设备独立性软件
-
向上层提供统一的调用接口(read/write系统调用)
-
设备保护
-
差错处理
-
设备的分配与回收
-
数据缓冲区管理
-
建立逻辑设备名到物理设备名的映射关系(维护一张逻辑设备表LUT),根据设备类型选择调用相应的驱动程序
多用户操作系统中,每个用户登录时会创建一个用户管理进程,而LUT就存放在该进程的PCB中
设备驱动程序
主要负责对硬件设备的具体控制,将上层发出的一系列命令,转化为特定硬件设备能理解的操作,比如设置设备寄存器,检查设备状态等。
中断处理程序
-
从控制器读出设备状态
-
判断I/O是否正常结束
- 是:从设备中读入一个字的数据并经由CPU放到内存缓冲区中
- 否:根据异常原因做相应处理
硬件
不同的I/O设备有不同的硬件特性,具体细节只有厂家清楚,故由厂家设计并提供驱动程序
驱动程序一般以一个独立的进程的方式存在
I/O应用程序接口
位于用户层I/O软件与设备独立软件之间
字符设备接口
使用get/put系统调用,向字符设备读/写一个字符
字符设备并没有地址的概念
块设备接口
使用read/write系统调用向块设备的读写指针位置读/写多个字符
使用seek系统调用修改读写指针位置
网络设备接口
又称网络套接字(socket)接口
使用socket系统调用,创建一个网络套接字,指明网络协议(UDP还是TCP)
- 在内核空间申请一片区域,用于接收发送数据,给用户进程返回一个指向自身的指针(描述符fd)
bind:将套接字绑定到某本地端口,将套接字作为端口号
connect:将套接字连接到远程地址,在应用层实现连接,传输层决定使用UDP还是TCP连接
read/write:从套接字读/写数据,由设备独立性软件负责实现
阻塞与非阻塞I/O
阻塞I/O:应用发出I/O系统调用,进程进入阻塞态等待
- 比如字符设备接口
非阻塞I/O:应用程序发起I/O系统调用,系统调用可迅速返回,进程无需阻塞等待
- 比如块设备接口
设备驱动程序接口
介于设备独立性软件与驱动程序之间
设备驱动接口要求厂商必须设计符合规范的驱动程序
- 该规范统一了驱动程序的函数名,参数类型,参数数量等
I/O核心子系统
即设备独立性软件+设备驱动程序+中断处理程序
设备独立性软件:I/O调度、设备保护、设备分配与回收、缓冲区管理
I/O调度
用某种算法确定一个处理I/O请求的顺序
比如磁盘调度与文件调度相关算法,详见文件管理第11节
设备保护
在UNIX系统中,设备被看作是一种特殊的文件,每个设备也会有相应的FCB,
与正常的文件保护类似,详见文件管理第7节
假脱机技术
脱机技术
脱离主机的控制进行的输入/输出操作,最早期的系统通过磁带完成了脱机技术,预先将输入的数据通过外围设备输入到磁带中,再将磁带放入主机进行处理,结果输出到磁带通过外围设备读取,不需要CPU干预
- 缓解CPU与慢速I/O设备的速度矛盾
假脱机技术
通过软件的方式模拟脱机技术,又称SPOOLing技术
- 在磁盘中开辟两个存储区域,对应输入井和输出井
- 输入井模拟脱机技术的磁带,收容I/O设备输入的数据
- 输出井模拟脱机输出时的磁带,收容用户进程输出的数据
额外的,需要创建输入进程和输出进程,模拟脱机输入输出时的外围控制机
- 需要和用户进程并发运行,需要多道程序技术支持
- 输入进程管理输入缓冲区,暂存输入设备输入的数据,在转送到输入井
- 输出进程管理输出缓冲区,暂存输出井发来的数据,转送到输出设备
输入、输出缓冲区都位于内存的缓冲区
设备的分配与回收
总原则是充分发挥设备的使用效率,尽可能让设备忙碌,同时避免不合理分配导致的进程死锁。
设备分配数据结构
主要由设备控制表DCT、控制器控制表COCT、通道控制表CHCT和系统设备表SDT组成
DCT:一个DCT就表征一个设备,表项就是设备的各个属性,并含一个请求本设备未满足的请求队列的首指针,指向请求队列的首PCB
COCT:含一个存放与控制器连接的通道控制表指针
CHCT:一个通道可为多个控制器服务,故含一个指向控制器表首址的指针
SDT:整个系统只有一张,记录已连接到系统的所有物理设备的情况,每个物理设备占一个条目
设备分配步骤
- 根据进程请求的物理设备名查找SDT
- 根据SDT找到DCT,若设备忙碌则将进程PCB挂到设备等待队列中,不忙碌就分配设备给进程
- 根据DCT找到COCT,若控制器忙碌,就将PCB挂到控制器等待队列,不忙碌就分配控制器给进程
- 根据COCT找到CHCT,若通道忙碌就将PCB挂到通道等待队列,否则分配通道给进程
只有设备、控制器、通道都就绪,设备分配才算成功
分配步骤改进
针对物理设备建立一个逻辑设备名与物理设备名的逻辑设备表LUT,
- 用户编程时只需提供逻辑设备名(设备类型)查找SDT
- 查找SDT、寻找用户指定类型的、空闲的设备、分配给进程,并在LUT中新增一个表项
- 其余步骤与改进前相同
设备分配策略
设备分配方式:
- 静态分配:主用于独占设备的分配,作业执行前,系统一次性分配所需全部资源,运行期作业独占资源,直到作业撤销,不发生死锁
- 动态分配:进程需要设备时通过系统调用发出设备请求,由系统按某种策略分配设备
设备分配算法:
- 独占设备:静态、动态分配均可,一般用静态分配
- 共享设备:一般采用动态分配方式,但在每一个I/O传输单位时间内,仅被一个设备占有,通常采用先请求先分配和优先级高者优先算法。
设备分配安全性
- 安全分配方式:进程每发出I/O请求就进入阻塞态,直到I/O操作完成才被唤醒
- 不会发生死锁,CPU和I/O串行工作
- 不安全分配方式:进程发出I/O请求后继续运行,只有当进程所请求的设备已被另一进程占用时才进入阻塞态
- 有可能发生死锁
缓冲区管理
可以用专门的硬件寄存器组成,也可以使用内存作为缓冲区
- 缓和CPU与I/O设备之间速度不匹配的矛盾
- 减少对CPU的中断频率、放宽CPU中断响应时间的限制
- 解决数据粒度不匹配的问题,即输出进程每次可以产生一块数据,但I/O设备每次只能输出一个字符
- 提高CPU与I/O设备之间的并行性
当缓冲区非空时,不能往缓冲区冲入数据,只能从缓冲区把数据传出,当缓冲区为空时,可以往缓冲区冲入数据,但必须把缓冲区充满后,才能从缓冲区把数据传出。
单缓冲
主存为用户进程分配一个缓冲区,用户进程的内存空间再分出一片与缓冲区大小相同的工作区用于接收/传送数据
计算每处理一块数据平均所需时间:
- 设初始状态为工作区满,缓冲区空
- 分析CPU处理工作区数据时间C、块设备输入到缓冲区的时间T、缓冲区传送到工作区的时间M
- 分析从初始态又回到初始态一共需要多长时间(画甘特图)
故处理一块数据平均耗时Max(C,T)+M
双缓冲策略
当用户进程请求块设备读入若干块数据,系统在主存中为其分配两个缓冲区
计算每处理一块数据平均所需时间:
- 初始状态设为工作区空,其中一个缓冲区满,另一个缓冲区空
- 画甘特图分析
处理一块数据平均耗时Max(T,C+M)
两个互相通信的机器只设置单缓冲区,在任意时刻只能实现数据的单项传输
双缓策略任意时刻可以实现双向的数据传送
循环缓冲区
将多个大小相等的缓冲区链接成一个循环队列
设置两个指针,in指针指向下一个可以冲入数据的空缓冲区,out指针指向下一个可以取出数据的满缓冲区
缓冲池
由系统共用的缓冲区组成,按使用状况可以分为:空缓冲队列、满输入缓冲队列、满输出缓冲队列
同时设置四种工作缓冲区
- 输入进程请求输入数据:从空缓冲队列取出一块作为hin,冲满数据后挂到输入队列队尾
- 计算进程想要取得一块输入数据:从满输入缓冲队列取出一块作为sin,读空后挂到空缓冲队列
- 计算进程想要将准备好的数据冲入缓冲区:从空缓冲队列取出一块作为hout,数据冲满后将缓冲区挂到输出队列队尾
- 输出进程请求输出数据:从输出队列中取得一块充满输出数据的缓冲区作为sout,缓冲区读空后挂到空缓冲区队列