操作系统第五章 设备管理
第五章 设备管理
5.1 I/O设备介绍
本节介绍I/O设备,并不设计OS中I/O是如何管理的
5.1.1 I/O设备的概念
- “I/O”就是“输入/输出”(Input/Output)
- I/O设备就是
可以将数据输入到计算机
,或者可以接收计算机输出数据
的外部设备,属于计算机中的硬件部件
。
鼠标、键盘――典型的输入型设备 | 显示器——输出型设备 | 移动硬盘——即可输入、又可输出的设备 |
---|---|---|
![]() |
![]() |
![]() |
UNIX系统将外部设备抽象为一种特殊的文件
,用户可以使用与文件操作相同的方式对外部设备进行操作
。
- Write操作:向外部设备写出数据
- Read操作:从外部设备读入数据
5.1.2 设备的分类
(1) 按使用特性分类
- 人机交互类外设:鼠标、键盘、打印机等――用于人机交互
- 存储设备:移动硬盘、光盘等――用于数据存储
- 网络通信设备:调制解调器等――用于网络通信,比如modem,网络路由器等
人机交互类外设 | 存储设备 | 网络通信设备 |
---|---|---|
![]() |
![]() |
![]() |
从传输速度来看:
- 人机交互类外设传输速度慢
- 存储设备 传输速度快
(2) 按传输速率分类
- 有印象即可,不会考察,因为高中低速没有明确的界限
- 低速设备:鼠标、键盘等――传输速率为
每秒几个到几百字节
- 中速设备:如激光打印机等――传输速率为
每秒数千至上万个字节
- 高速设备:如磁盘等一一传输速率为
每秒数千字节至千兆字节的设备
低速设备 | 中速设备 | 高速设备 |
---|---|---|
![]() |
![]() |
![]() |
(3) 按信息交换的单位分
- 块设备:如磁盘等――数据传输的基本单位是“块”。
传输速率较高
,可寻址
,即对它可随机地读/写任一块
- 字符设备:鼠标、键盘等――数据传输的基本单位是字符。
传输速率较慢
,不可寻址
,在输入/输出时常采用中断驱动方式
块设备 | 字符设备 |
---|---|
![]() |
![]() |
- 重点关注按信息交换的单位分类
5.2 I/O控制方式
研究的问题是:用什么样的方式来控制I/O设备的数据读/写
需要注意的问题:
- 完成一次读/写操作的流程;
- CPU干预的频率;
- 数据传送的单位;
- 数据的流向;
- 主要缺点和主要优点。
5.2.1 程序直接控制方式(轮询)
- CPU发出指令后,还需要不断地查询,因为设备可能还未启动
- 每次读取只能读取一个字
完成一次读/写操作的流程;
- 这里有个问题,为什么CPU的寄存器要写入到内存中呢?
- 因为程序中使用的数据都是在内存中的,程序不能直接读取CPU的寄存器吧
#include<stdio.h>
#include<stdlib.h>
int main() {
int a, b, c, d;
scanf("%d", &a); // 输入的数据最终要放到内存中(a/b/c/d变量存放在内存中)
scanf("%d", &b);
printf("a+b=%d\n", a+b);
scanf("%d %d", &c, &d);
printf("c*d=%d\n", c*d); // 同理,输出的变量也要存放在内存中,需要从内存中取出
system("pause");
return 0;
}
-
CPU千预的频率:很频繁,I/O操作开始之前、完成之后需要CPU介入,并且在等待l/O完成的
过程中CPU需要不断地轮询检查
。 -
数据传送的单位:每次读/写一个字
-
数据的流向
- 读操作(数据输入):I/O设备→
CPU
→内存 - 写操作(数据输出):内存→
CPU
→I/O设备
每个字的读/写都需要CPU的帮助
- 读操作(数据输入):I/O设备→
-
优缺点:
-
优点:
实现简单。在读/写指令之后,加上实现循环检查的一系列指令即可(因此才称为“程序直接控制方式”)
-
缺点:
CPU和I/O设备只能串行工作
- CPU需要一直轮询检查,长期处于“忙等”状态,CPU利用率低。
- 输入输出都需要经过CPU
-
5.2.2 中断驱动方式
引入中断机制
。
- 由于I/O设备速度很慢,因此在CPU发出读/写命令后,可
将等待l/O的进程阻塞,先切换到别的进程执行
。 - 当I/O完成后,控制器会
向CPU发出一个中断信号
,CPU检测到中断信号后,会保存当前进程的运行环境信息,转去执行中断处理程序处理该中断。 - 处理中断的过程中,CPU从I/O控制器
读一个字
的数据传送到CPU寄存器,再写入主存。 - 接着,CPU恢复等待l/O的进程(或其他进程)的运行环境,然后继续执行。
注意:
-
CPU会在
每个指令周期的末尾检查中断
; -
中断处理过程中需要保存、恢复进程的运行环境,这个过程是需要一定时间开销的。可见,如果中断发生的频率太高,也会降低系统性能。
(由于每次读取一个字,也就是说,每读一个字就要一次中断;如果读大量数据的话,性能就会降低很多)
- 完成一次读/写操作的流程;
- CPU干预的频率
每次I/O操作开始之前、完成之后需要CPU介入。等待l/O完成的过程中CPU可以切换到别的进程执行。
CPU是不需要轮询的,设备准备好了之后给CPU中断
- 数据传送的单位:每次读/写
一个字
- 数据的流向:
- 读操作(数据输入): I/O设备→
CPU
→内存 - 写操作(数据输出):内存→
CPU
→>I/O设备
- 读操作(数据输入): I/O设备→
- 主要缺点和主要优点
优点
:与“程序直接控制方式”相比,在“中断驱动方式”中,I/O控制器会通过中断信号主动报告I/o已完成,CPU不再需要不停地轮询。CPU和I/o设备可并行工作,CPU利用率得到明显提升
。缺点
:- 每个字在I/O设备与内存之间的传输,都需要经过CPU。
- 而频繁的中断处理会消耗较多的CPU时间。
5.2.3 DMA方式
这个解决了上面的两个问题
- 不需要CPU作为中介
- 每次传入一个块
与“中断驱动方式
”相比,DMA方式(Direct Memory Access,直接存储器存取。主要用于块设备的I/O控制)有这样几个改进:
- 数据的传送单位是“块”。不再是一个字、一个字的传送;
- 数据的流向是从设备直接放入内存,或者从内存直接到设备。不再需要CPU作为中介。
- 仅在传送一个或多个数据块的开始和结束时,才需要CPU千预。
- 完成一次读/写操作的流程;
DMA控制器
- DMA控制器类似于IO控制器(也是由CPU和控制器的接口(寄存器),IO控制逻辑,控制器和外设的接口组成的)
寄存器 | 说明 |
---|---|
DR(Data Register,数据寄存器) | 暂存从设备到内存,或从内存到设备的数据。 |
MAR (Memory Address Register,内存地址寄存器) | 输入时,MAR表示数据应放到内存中的什么位置 输出时,MAR表示要输出的数据放在内存中的什么位置。 |
DC (Data Counter,数据计数器) | 表示剩余要读/写的字节数。 |
CR (Command Register,命令/状态寄存器) | 用于存放CPU发来的I/O命令,或设备的状态信息。 |
一个DMA控制器可能控制多个设备,同样地,寄存器可能也不止一组,可能一个设备对应一组寄存器
-
DMA也不是一下就能读一块,实际上也是一个字一个字地读取每次读取都缓存到DR中然后再写到内存中
只不过对于CPU来说,读/写完一块之后才需要CPU处理
- CPU千预的频率:仅在
传送一个或多个数据块的开始和结束时
,才需要CPU千预。
注意,这里传送的多个数据块必须是连续的,如果不连续的话,那么也需要CPU处理多次
- 数据传送的单位:每次读/写一个或多个块(注意:每次读写的只能是连续的多个块,且这些块读入内存后在内存中也必须是连续的)
- 数据的流向(不再需要经过CPU)
- 读操作(数据输入) : I/O设备→内存
- 写操作(数据输出):内存→I/O设备
- 主要缺点和主要优点
- 优点:
- 数据传输以“块”为单位,CPU介入频率进一步降低。
- 数据的传输不再需要先经过CPU再写入内存,数据传输效率进一步增加。
- CPU和I/O设备的并行性得到提升。
- 缺点:
- CPU每发出一条l/O指令,只能读/写一个或多个连续的数据块。
- 如果要读/写多个离散存储的数据块,或者要将数据分别写到不同的内存区域时,CPU要分别发出多条I/O指令,进行多次中断处理才能完成。
- 优点:
5.2.4 通道控制方式
- 通道:一种硬件,可以理解为是“简化版的CPU”。通道可以
识别并执行一系列通道指令
- 通道程序是存在于内存当中的一段程序,操作系统向通道发出指令之后,通道读取通道程序进行读取操作
- 与CPU相比,通道可以执行的指令很单一,并且
通道程序是放在主机内存中的
,也就是说通道与CPU共享内存
- 与通道直接连接的是IO控制器,而不是IO设备;一个通道可以控制多个IO控制器,一个IO控制器可以控制多个IO设备
- 完成一次读写的流程
- CPU千预的频率:极低,通道会根据CPU的指示执行相应的通道程序,
只有完成一组数据块的读/写后才需要发出中断信号
,请求CPU千预。 - 数据传送的单位:每次读/写一组
数据块
- 数据的流向(在通道的控制下进行)
- 读操作(数据输入): I/O设备→内存
- 写操作(数据输出):内存→I/O设备
- 主要缺点和主要优点
- 缺点:实现复杂,需要专门的通道硬件支持
- 优点:CPU、通道、I/o设备可并行工作,资源利用率很高。
5.2.5 比较
寇成一次读/写的过程 | CPU干预频率 | 每次I/O的数据传输单位 | 数据流向(输入) | 数据流向(输出) | 优点 | 缺点 | |
---|---|---|---|---|---|---|---|
程序直接控制方式 | CPU发出I/O命令后需要不断轮询 | 极高 | 字 | 设备→CPU→内存 | 内存→CPU→设备 | 实现简单。在读/写指令之后,加上实现循环检查的一系列指令即可(因此才称为“程序直接控制方式”) | 1.CPU和I/O设备只能串行工作 2.CPU需要一直轮询检查,长期处于“忙等”状态,CPU利用率低。 3.输入输出都需要经过CPU |
中断驱动方式 | CPU发出I/O命令后可以做其他事,本次I/O完成后设备控制器发出中断信号 |
高 | 字 | 设备→CPU→内存 | 内存→>CPU→设备 | 与“程序直接控制方式”相比,在“中断驱动方式”中,I/O控制器会通过中断信号主动报告I/o已完成,CPU不再需要不停地轮询。CPU和I/o设备可并行工作,CPU利用率得到明显提升 。 |
1.每个字在I/O设备与内存之间的传输,都需要经过CPU。 2.而频繁的中断处理会消耗较多的CPU时间。 |
DMA方式 | CPU发出I/O命令后可以做其他事,本次I/O完成后DMA控制器发出中断信号 |
中 | 块/连续的块 | 设备→内存 | 内存→设备 | 1.数据传输以“块”为单位,CPU介入频率进一步降低。 2.数据的传输不再需要先经过CPU再写入内存,数据传输效率进一步增加。 3.CPU和I/O设备的并行性得到提升。 |
1.CPU每发出一条l/O指令,只能读/写一个或多个连续的数据块。 2.如果要读/写多个离散存储的数据块,或者要将数据分别写到不同的内存区域时,CPU要分别发出多条I/O指令,进行多次中断处理才能完成。 |
通道控制方式 | CPU发出I/O命令后可以做其他事。通道会执行通道程序以完成I/O,完成后通道向CPU发出中断信号 |
低 | 一组块 | 设备→内存 | 内存→设备 | CPU、通道、I/O设备可并行工作,资源利用率很高。 | 实现复杂,需要专门的通道硬件支持 |
每一个阶段的优点都是解决了上一阶段的最大缺点。
总体来说,整个发展过程就是要
尽量减少CPU对I/O过程的干预,把CPU从繁杂的I/O控制事务中解脱出来,以便更多地去完成数据处理任务
。
5.3 I/O设备硬件(I/O控制器)
I/O设备由机械部件和电子部件组成
5.3.1 机械部件
- I/O设备的
机械部件
主要用来执行具体I/O操作
。 - 如我们看得见摸得着的
鼠标/键盘的按钮
;显示器的LED屏
;移动硬盘的磁臂、磁盘盘面
。
5.3.2 电子部件(I/O控制器)
本节考察频率不高
- I/O设备的
电子部件通常是一块插入主板扩充槽的印刷电路板
。 - CPU
无法直接控制I/O设备的机械部件
,因此I/O设备还要有一个电子部件作为CPU和I/O设备机械部件之间的“中介”
,用于实现CPU对设备的控制
。 - 这个电子部件
就是I/O控制器,又称设备控制器
。 - CPU可控制I/O控制器,又由I/O控制器来控制设备的机械部件。
(1) I/O控制器的功能
下面分别解释一下电子部件的功能
功能 | 说明 |
---|---|
接受和识别CPU发出的命令(和参数) | 如CPU发来的read/write 命令,I/O控制器中会有相应的控制寄存器 来存放命令和参数(主要还是参数,命令直接通过控制线传输了) |
向CPU报告设备的状态 | l/O控制器中会有相应的状态寄存器 ,用于记录I/O设备的当前状态 。如:1表示空闲,0表示忙碌 |
数据交换 | I/O控制器中会设置相应的数据寄存器 。输出时 ,数据寄存器用于暂存CPU发来的数据 ,之后再由控制器传送设备。输入时 ,数据寄存器用于暂存设备发来的数据 ,之后CPU从数据寄存器中取走数据。 |
地址识别 | 类似于内存的地址,为了区分设备控制器中的各个寄存器 ,也需要给各个寄存器设置一个特定的“地址” 。I/O控制器通过CPU提供的“地址”来判断CPU要读/写的是哪个寄存器 |
(2) I/O控制器的组成
IO控制器主要由三部分组成:
- CPU与控制器的接口:用于实现
CPU与控制器之间的通信
。CPU通过控制线
发出命令;通过地址线
指明要操作的设备;通过数据线
来取出(输入)数据,或放入(输出)数据 - I/O逻辑: 负责
接收和识别CPU的各种命令
(如地址译码),并负责对设备发出命令 - 控制器与设备的接口:用于实现控制器与设备之间的通信(一个设备控制器有多个接口可能连接多个设备,因此要为这些设备编号;或者给设备一个地址,CPU在发出IO命令的时候,需要指明访问的是哪个设备)
CPU操纵I/O的流程
-
CPU通过控制线向IO逻辑发出指令,并且通过地址线说明要操纵的是哪个设备
-
如果是输出数据的话,会先将数据放到数据寄存器中,然后IO逻辑从数据寄存器中取出数据
如果发出的指令有参数,那么参数会放到控制寄存器中,IO逻辑从控制器中读出参数
为了实现对设备的管理,CPU还会从状态寄存器中读出设备的状态;IO逻辑会向状态寄存器中写入各个设备的状态
-
然后IO逻辑将数据通过 控制器与设备的接口将数据输出(如果是输入的话IO逻辑也要将数据放到数据寄存器中)
-
设备要通过 控制器与设备的接口写入状态,IO逻辑会写到对应的状态寄存器中
-
除了传输数据,还能向设备发出控制命令让其执行相应的工作
细节:
- 一个IO控制器可能对应多个设备
- 数据寄存器、控制寄存器、状态寄存器可能有多个(如:每个控制/状态寄存器对应一个具体的设备),且这些寄存器都要有相应的地址,才能方便CPU操作。有的计算机会
让这些寄存器占用内存地址的一部分
,称为内存映像l/O
;另一些计算机则采用I/O专用地址
,即寄存器独立编址
。
(3) I/O寄存器的编址
这里是寄存器的编制,而不是设备接口的编址吧
说明 | 优缺点 | |
---|---|---|
内存映像I/O | 内存映射I/O。控制器中的寄存器与内存地址统一编址 | 优点 :简化了指令。可以采用对内存进行操作的指令来对控制器进行操作 |
寄存器独立编址 | 寄存器独立编制。控制器中的寄存器使用单独的地址 | 缺点 :需要设置专门的指令 来实现对控制器的操作 ,不仅要指明寄存器的地址 ,还要指明控制器的编号 |
内存映像I/O | 寄存器独立编址 |
---|---|
![]() |
![]() |
- 有的可能将不同设备控制器的寄存器连续编址,比如右图中是0 1 2 3 4 5
5.4 I/O软件层次(概述)
主要讲解I/O各个软件层次的功能
5.4.1 软件层次结构
前面讲解了I/O的硬件结构,现在讲软件层次结构
- 越上面的层次越接近用户;越下面的层次越接近硬件
- 中间的部分属于操作磁头的内核部分
设备驱动程序
和设备独立性软件
是直接接触硬件的(可以看到上面有一条横线)- 每一层会利用其下层提供的服务,实现某些功能,并屏蔽实现的具体细节,向高层提供服务(“封装思想”)(这一点和计算机网络类似)
下面逐层讲解每一层的作用
5.4.1 用户层软件
Windows操作系统向外提供的一系列
系统调用
,但是由于系统调用的格式严格,使用麻烦,因此在用户层上封装了一系列更方便的库函数
接口供用户使用(Windows API)
- printf函数会被翻译成等价的 write系统调用
用户层软件也是给I/O一个接口了
5.4.2 I/O核心子系统
- I/O核心子系统要实现的功能其实就是中间三层要实现的功能
考研中,我们需要重点理解和掌握的功能是:
I/O调度
、设备保护
、假脱机技术(SPOOLing技术)
、设备分配与回收
、缓冲区管理(即缓冲与高速缓存)
这些功能分别在哪里实现
其中
- I/O调度:用某种算法确定一个好的顺序来处理各个l/O请求。
如:磁盘调度(先来先服务算法、最短寻道优先算法、SCAN算法、C-SCAN算法、LOOK算法、C-LOOK算法)。当多个磁盘I/O请求到来时,用某种调度算法确定满足I/O请求的顺序。
同理,打印机等设备也可以用先来先服务算法、优先级算法、短作业优先等算法来确定I/O调度顺序。
-
设备保护:操作系统需要实现文件保护功能,不同的用户对各个文件有不同的访问权限(如:只读、读和写等)。
在UNIX系统中,
设备被看做是一种特殊的文件,每个设备也会有对应的FCB
。当用户请求访问某个设备时,系统根据FCB中记录的信息来判断该用户是否有相应的访问权限,以此实现“设备保护”的功能。(参考“文件保护”小节
)
5.5 I/O软件层次(用户层软件)
5.5.1 假脱机技术
(1) 脱机技术的产生
首先回顾一下计算机发展的历史
- 手工操作阶段:主机直接从l/O设备获得数据,由于设备速度慢,主机速度很快,
人机速度矛盾明显
,主机要浪费很多时间来等待设备
批处理阶段引入了 脱机输入/输出技术(用磁带完成)
- 输入时:在外围控制机的控制下,慢速输入设备的数据先被输入到更快速的磁带上。之后主机可以从快速的磁带上读入数据,从而缓解了速度矛盾
- 输出时类似
Tips:为什么称为“脱机”—―脱离主机的控制进行的输入/输出操作,输入和输出是外围控制机实现的。
引入脱机技术后,缓解了CPU与慢速l/O备的速度矛盾。另一方面,即使CPU在忙碌,也可以提前将数据输入到磁带;即使慢速的输出设备正在忙碌,也可以提前将数据输出到磁带(也就是I/O和CPU可以并行工作了)
脱机技术的作用:缓解设备与CPU的速度矛盾,实现预输入、缓输出
,I/O设备可以和CPU并行工作了。
(2) 假脱机技术(SPOOLing)
可以看这篇博客
“假脱机技术”,又称“SPOOLing技术”是用软件的方式模拟脱机技术
。
SPOOLing系统的组成如下:
- 在磁盘上开辟出两个存储区域——“输入井”和“输出井”
- 要实现SPOOLing技术,必须要有
多道程序技术的支持
。系统会建立“输入进程”和“输出进程”
下面对比脱机技术说明
-
“
输入井
”模拟脱机输入时的磁带
,用于收容I/O设备输入的数据;“输出井
”模拟脱机输出时的磁带
,用于收容用户进程输出的数据 -
“
输入进程
”模拟脱机输入时的外围控制机
;“输出进程
”模拟脱机输出时的外围控制机
-
在
输入进程
的控制下,“输入缓冲区
”用于暂存从输入设备输入的数据
,之后再转存到输入井
中;在输出进程
的控制下,“输出缓冲区”用于暂存从输出井送来的数据,之后再传送到输出设备上注意,输入缓冲区和输出缓冲区是在内存中的缓冲区
脱机技术的目的是
缓解CPU与慢速IO设备
,那么假脱机技术也不例外;脱机技术实现的中介是磁盘
,那么假脱机技术实现的中介就是内存
吧
(3) 共享打印机原理分析
首先对设备进行分类
- 独占式设备——只允许各个进程串行使用的设备。一段时间内只能满足一个进程的请求。
- 共享设备——允许多个进程“同时”使用的设备(宏观上同时使用,微观上可能是交替使用)。可以同时满足多个进程的使用请求。
打印机是种“独占式设备”,例子:若进程1正在使用打印机,则进程2请求使用打印机时必然阻塞等待
但是可以用SPOOLing技术改造成“共享设备”
原理如下
当多个用户进程提出输出打印的请求
时,系统会答应它们的请求,但是并不是真正把打印机分配给他们,而是由假脱机管理进程为每个进程做两件事:
- 在磁盘
输出井
中为进程申请一个空闲缓冲区
(也就是说,这个缓冲区是在磁盘上的),并将要打印的数据送入其中
- 为用户进程申请一张
空白的打印请求表
,并将用户的打印请求填入表中(其实就是用来说明用户的打印数据存放位置等信息的),再将该表挂到假脱机文件队列上。
当打印机空闲
时,输出进程会从文件队列的队头取出一张打印请求表
,并根据表中的要求将要打印的数据从输出井传送到输出缓冲区
,再输出到打印机进行打印
。用这种方式可依次处理完全部的打印任务
- 虽然系统中只有一个台打印机,但每个进程提出打印请求时,系统都会为在输出井中为其分配一个存储区(相当于分配了一个逻辑设备),使每个用户进程都觉得自己在独占一台打印机,从而实现对打印机的共享。
- SPOOLing技术可以把一台物理设备虚拟成逻辑上的多台设备,可将独占式设备改造成共享设备。
分析一下SPOOLing的作用:
- 如果不采用SPOOLing技术的话,那么用户程序会直接将请求和数据通过操作数据发给I/O,这样肯定不可能实现共享了。同时设备也只能由一个使用
- 但是采用了SPOOLing技术,可以将数据先存到磁盘里面,打印任务先存到内存的数据进程队列里面,打印机打印的时候自己从队列中找
- 为啥数据不放到内存中呢?因为如果要取的话还需要CPU去取,放到磁盘里面就不用主机了
- 所以就是将打印的任务和数据一口气给了磁盘和内存,然后主机该干嘛干嘛,剩下的打印机自己去取就行了,CPU就
不用阻塞
了 - 主要还是解决的因为CPU和I/O因速度不一致造成的阻塞问题,同时资源利用率低的问题
类似于虚拟处理器,只不过虚拟处理器是骗用户的,假脱机技术骗进程的
5.6 I/O软件层次(设备独立性软件)
这个只是介绍一部分设备独立性软件的功能
设备独立性软件,又称设备无关性软件
。与设备的硬件特性无关的功能
几乎都在这一层实现。
功能
:
-
向上层提供统一的调用接口(如read/write系统调用)
-
设备的保护:原理类似与文件保护。设备被看做是一种特殊的文件,不同用户对各个文件的访问权限是不一样的,同理,
对设备的访问权限也不一样
。 -
差错处理(了解):设备独立性软件需要对一些设备的错误进行处理
-
设备的分配与回收
-
数据缓冲区管理:可以通过缓冲技术屏蔽设备之间数据交换单位大小和传输速度的差异
-
建立
逻辑设备名
到物理设备名
的映射关系(逻辑设备表);根据设备类型选择调用相应的驱动程序
(这也是设备逻辑表LUT
的作用)
其中,主要要掌握的功能有
设备的分配与回收
、数据缓冲区管理
5.6.1 设备的分配与回收
这是独立性软件实现的功能
(1) 设备分配时应考虑的因素
设备的固有属性可分为三种:独占设备、共享设备、虚拟设备。
- 独占设备——一个时段只能分配给一个进程(如打印机)
- 共享设备——可同时分配给多个进程使用(如磁盘),各进程往往是
宏观上同时共享使用设备,而微观上交替使用。
- 虚拟设备——采用SPOOLing 技术将独占设备改造成虚拟的共享设备,可同时分配给多个进程使用(如采用SPOOLing技术实现的共享打印机)
设备的分配算法:先来先服务、优先级高者优先、短任务优先
设备分配的安全性
从进程运行的安全性上考虑,设备分配有两种方式:
-
安全分配方式:为进程分配一个设备后就将进程阻塞,本次I/O完成后才将进程唤醒(eg:考虑进程请求打印机打印输出的例子)
一个时段内每个进程只能使用一个设备
- 优点:破坏了“请求和保持”条件,不会死锁
- 缺点:对于一个进程来说,CPU和I/O设备只能串行工作
-
不安全分配方式:进程发出I/o请求后,系统为其分配/O设备,进程可继续执行,之后还可以发出新的I/O请求。只有某个l/O请求得不到满足时才将进程阻塞。
一个进程可以同时使用多个设备
- 优点:进程的计算任务和I/O任务可以并行处理,使进程迅速推进
- 缺点:有
可能发生死锁
(死锁避免、死锁的检测和解除)
(2) 静态分配和动态分配
- 静态分配:进程运行前为其分配全部所需资源,运行结束后归还资源(破坏了“请求和保持”条件,不会发生死锁)
- 动态分配:进程运行过程中动态申请设备资源
(3) 设备分配管理中的数据结构
“设备、控制器、通道”之间的关系:
- 一个通道可控制多个设备控制器,每个设备控制器可控制多个设备。
- 数据结构就要表示这种从属关系
设备控制表(DCT)
:系统为每个设备
配置一张DCT,用于记录设备情况
设备控制表(DCT) | 表项的说明 |
---|---|
设备类型 | 如:打印机/扫描仪/键盘 |
设备标识符 | 即物理设备名 ,系统中的每个设备的物理设备名唯一 |
设备状态 | 忙碌/空闲/故障... |
指向控制器表的指针 | 每个设备由一个控制器控制,该指针可找到相应控制器的信息 |
重复执行次数或时间 | 当重复执行多次l/O操作后仍不成功,才认为此次I/O失败 |
设备队列的队首指针 | 指向正在等待该设备 的进程队列 (由进程PCB组成队列) |
注:“进程管理”章节中曾经提到过“系统
会根据阻塞原因不同
,将进程PCB挂到不同的阻塞队列中
控制器控制表(COCT)
:每个设备控制器
都会对应一张COCT。操作系统根据COCT的信息对控制器进行操作和管理。
控制器控制表(COCT) | 表项的说明 |
---|---|
控制器标识符 | 各个控制器的唯一ID |
控制器状态 | 忙碌/空闲/故障... |
指向通道表的指针 | 每个控制器由一个通道控制,该指针可找到相应通道的信息 |
控制器队列的队首指针 | 指向正在等待该控制器的进程队列(由进程PCB组成队列) |
控制器队列的队尾指针 |
通道控制表(CHCT)
:每个通道
都会对应一张CHCT。操作系统根据CHCT的信息对通道进行操作和管理。
通道控制表(CHCT) | 表项的说明 |
---|---|
通道标识符 | 各个通道的唯一ID |
通道状态 | 忙碌/空闲/故障... |
与通道连接的控制器表 首址 |
可通过该指针找到该通道管理的所有控制器相关信息(COCT) |
通道队列的队首指针 | 指向正在等待该通道的进程队列(由进程PCB组成队列) |
通道队列的队尾指针 |
系统设备表(SDT)
:记录了系统中全部设备的情况,每个设备对应一个表目。
系统控制表(SDT) |
---|
表面1 |
表面2 |
... |
表面i |
... |
用户用逻辑名称请求某个设备的时候,就是根据SDT查询物理设备名。也不对吧,逻辑名称和物理名称的映射是LUT保存的
设备分配的步骤
- 根据进程请求的物理设备名查找SDT(注:物理设备名是进程请求分配设备时提供的参数)
用户提供的是逻辑名称,根据设备独立性软件提供的
设备逻辑表
找到物理名称
- 根据
SDT
找到DCT
,若设备忙碌
则将进程PCB
挂到设备等待队列
中,不忙碌则将设备分配给进程
。 - 再根据
DCT
找到COCT
,若控制器忙碌
则将进程PCB
挂到控制器等待队列
中,不忙碌则将控制器分配给进程
。 - 再根据
COCT
找到CHCT
,若通道忙碌
则将进程PCB
挂到通道等待队列中
,不忙碌则将通道分配给进程
。
注∶只有设备、控制器、通道三者都分配成功时,这次设备分配才算成功,之后便可后动/O设备讲行数据传送
下面是我自己的理解为什么要这么找
- 首先进程要先能够得到设备的使用权,这是基础
- 得到设备之后,进程与设备的通信依次需要 管道 和 设备控制器,都是一对多的关系,所以先得到设备控制器的使用权
- 这里说一下为什么不能从上往下,假如先访问管道,那么管道已经被占满了,就进入队列等待,等到可以使用的时候,再请求设备控制器吗?但设备控制器可能也满了,要不然别的进程就不能使用
- 所以必须从下往上找
这种方式的缺点:
- 用户编程时必须使用“物理设备名”,底层细节对用户不透明,不方便编程
- 若换了一个物理设备,则程序无法运行
- 若进程请求的物理设备正在忙碌,则即使系统中还有同类型的设备,进程也必须阻塞等待
(比如说有三台打印机,第一台在使用中,但是程序中的物理设备名就是第一台,这个时候也会阻塞,而不会使用其他设备)
改进方法:建立逻辑设备名与物理设备名的映射机制,用户编程时只需提供逻辑设备名
逻辑设备名 | 物理设备名 | 驱动程序入口地址(不同类型的I/O设备需要有不同的驱动程序处理) |
---|---|---|
/dev/打印机1 | 3 | 1024 |
/dev/打印机2 | 5 | 2046 |
... | ... | ... |
- 逻辑设备表(LUT)建立了逻辑设备名与物理设备名之间的映射关系。
- 某用户进程
第一次使用设备时
使用逻辑设备名
向操作系统发出请求
,操作系统根据用户进程指定的设备类型
(逻辑设备名)查找系统设备表
,找到一个空闲设备分配给进程
,并在LUT中增加相应表项
。 - 如果之后用户进程再次通过相同的逻辑设备名请求使用设备,则操作系统通过LUT表即可知道用户进程实际要使用的是哪个物理设备了,并且也能知道该设备的驱动程序入口地址。
逻辑设备表的设置问题:
- 整个系统只有一张LUT:各用户所用的逻辑设备名不允许重复,适用于
单用户操作系统
- 每个用户一张LUT:不同用户的逻辑设备名可重复,适用于
多用户操作系统
5.6.2 缓冲区管理
(1) 缓冲区的定义和作用
- 缓冲区是一个
存储区域
,可以由专门的硬件寄存器
组成,也可利用内存作为缓冲区
。 - 使用
硬件作为缓冲区
的成本较高
,容量也较小
,一般仅用在对速度要求非常高的场合
(如存储器管理中所用的联想寄存器,由于对页表的访问频率极高,因此使用速度很快的联想寄存器来存放页表项的副本) - 一般情况下,更多的是利用
内存作为缓冲区
,“设备独立性软件
”的缓冲区管理
就是要组织管理好这些缓冲区
本节介绍的是"内存作为缓冲区"
缓冲区的作用
:
- 缓和CPU与I/O设备之间速度不匹配的矛盾
- 减少对CPU的中断频率,放宽对CPU中断相应时间的限制
- 解决数据粒度不匹配的问题(如:输出进程每次可以生成一块数据,但I/O设备每次只能输出一个字符)
- 提高CPU与I/O设备之间的并行性
很奇怪呀,那么和内存有什么区别呢?内存的作用也是这些啊。难道内存就是缓冲区吗?
我的理解是:
- 缓冲区不一定是内存,可以由专门的
硬件寄存器
组成- 内存一开始的任务也不是缓存,它仅仅是为了
缓和CPU与I/O设备之间速度不匹配的矛盾
,比如将程序全部移到内存中,这样CPU就不用每次从硬盘中访问,访问速度提升- 寄存器的速度比内存更快,不过价格更高,因此就先用内存实现了。
(2) 缓冲区分类
我觉得应该叫做缓冲区的发展
① 单缓冲
- 假设某用户进程
请求某种块设备读入若干块的数据
。若采用单缓冲的策略
,操作系统会在主存中为其分配一个缓冲区(若题目中没有特别说明,一个缓冲区的大小就是一个块
)。 - 注意:
当缓冲区数据非空时
,不能往缓冲区冲入数据,只能从缓冲区把数据传出
;当缓冲区为空时,可以往缓冲区冲入数据,但必须把缓冲区充满以后,才能从缓冲区把数据传出
。
为什么不直接传入用户进程的工作区呢?可能是并行性的问题吧?
用户进程的内存空间中,会分出一片工作区来接受输入/输出数据(一般也默认工作区大小与缓冲区相同)
常考题型:计算每处理一块数据平均需要多久?
技巧:假定一个
初始状态
,分析下次到达相同状态需要多少时间
,这就是处理一块数据平均所需时间
。
在“单缓冲”题型中,可以假设初始状态为工作区满,缓冲区空。
假设初始状态:工作区满,缓冲区空
假设T>C
T>C,因此CPU处理完数据后暂时不能将下一块数据传送到工作区,必须等待缓冲区中冲满数据
- 处理一块数据的平均用时=T+M
假设T < C
T<C,因此缓冲区中冲满数据后暂时不能继续冲入下一块数据,必须等待CPU处理结束后将数据从缓冲区传送到工作区
- 处理一块数据的平均用时=C+M
结论:采用单缓冲策略,处理一块数据平均耗时Max(C,T)+M
总结一下
各过程的时间 | T>C | T<C |
---|---|---|
![]() |
![]() |
![]() |
平均时间 | T + M | C + M |
② 双缓冲
其中两个缓冲区是地位相等的
- 假设某用户进程请求某种块设备读入若干块的数据。若采用双缓冲的策略,操作系统会在主存中为其分配两个缓冲区(若题目中没有特别说明,一个缓冲区的大小就是一个块)
- 双缓冲题目中,假设初始状态为:工作区空,其中一个缓冲区满,另一个缓冲区空
- 假设T>C+M
- 假设T < C + M
注:M(1)表示“将缓冲区1中的数据传送到工作区”;M(2)表示“将缓冲区2中的数据传送到工作区”
- 在第二个T后面的那半段:假设2T<2M+C,则I/设备将缓冲区1冲满时,缓冲区2的数据尚未取空,因此I/o设备暂时不能冲入数据
- 这种情况很难找到和初始状态一样的状态
- 总之,T<C+M意味着设备输入数据块的速度要比处理机处理数据块的速度更快。每处理一个数据块平均耗时C+M
结论:采用双缓冲策略,处理一个数据块的平均耗时为Max(T, C+M)
单、双缓冲通信时的区别
这里将的是通信
两台机器之间通信时,可以配置缓冲区用于数据的发送和接受。
显然,若两个相互通信的机器只设置单缓冲区,在任一时刻只能实现数据的单向传输
。
显然,若两个相互通信的机器只设置双缓冲区,在任一时刻可以实现双向的数据传输
③ 循环缓冲区
将多个大小相等的缓冲区链接成一个循环队列。
注:以下图示中,橙色表示已充满数据的缓冲区,绿色表示空缓冲区。
④ 缓冲池
- 缓冲池由
系统中共用的缓冲区
组成。这些缓冲区按使用状况
可以分为:空缓冲队列
、装满输入数据的缓冲队列
(输入队列)、装满输出数据的缓冲队列
(输出队列)。 - 另外,根据一个缓冲区在实际运算中扮演的功能不同,又设置了
四种工作缓冲区
:用于收容输入数据的工作缓冲区
(hin)、用于提取输入数据的工作缓冲区
(sin)、用于收容输出数据的工作缓冲区
( hout) 、用于提取输出数据的工作缓冲区
( sout)
工作流程如下:
- 输入进程请求输入数据:
- 从
空缓冲队列中取出一块
作为收容输入数据的工作缓冲区
(hin)。 冲满数据后
将缓冲区挂到输入队列队尾
- 从
![]() |
![]() |
---|
- 计算进程想要取得一块输入数据
- 从输入队列中取得一块冲满输入数据的缓冲区作为“提取输入数据的工作缓冲区(sin) ”。
- 缓冲区读空后挂到空缓冲区队列
![]() |
![]() |
---|
- 计算进程想要将准备好的数据冲入缓冲区
- 从空缓冲队列中取出一块作为“收容输出数据的工作缓冲区(hout) ”。
- 数据冲满后将缓冲区挂到输出队列队尾
![]() |
![]() |
---|
- 输出进程请求输出数据
- 从输出队列中取得一块冲满输出数据的缓冲区作为“提取输出数据的工作缓冲区( sout) ”。
- 缓冲区读空后挂到空缓冲区队列
![]() |
![]() |
---|
循环缓冲和缓冲池只要对原理有印象即可
5.6.3 物理逻辑映射
这个在上面概述里面提到过了
设备独立性软件的功能:建立逻辑设备名
到物理设备名
的映射关系(逻辑设备表);根据设备类型选择调用相应的驱动程序
(这也是设备逻辑表LUT
的作用)
映射关系如下
逻辑设备名 | 物理设备名 | 驱动程序入口地址(不同类型的I/O设备需要有不同的驱动程序处理) |
---|---|---|
/dev/打印机1 | 3 | 1024 |
/dev/打印机2 | 5 | 2046 |
... | ... | ... |
回想linux中的外设都是在/dev目录下的,实际上就是通过设备独立性软件进行了映射吧
操作系统系统可以采用两种方式管理逻辑设备表(LUT) :
- 第一种方式,
整个系统
只设置一张LUT,这就意味着所有用户不能使用相同的逻辑设备名
,因此这种方式只适用于单用户操作系统
。 - 第二种方式,为
每个用户
设置一张LUT,各个用户使用的逻辑设备名可以重复,适用于多用户操作系统
。系统会在用户登录时为其建立一个用户管理进程,而LUT就存放在用户管理进程的PCB
中。
类似于文件目录的单级目录和两级目录
5.7 I/O软件层次(各层接口)
这个主要还是讲每层的接口的
5.7.1 输入输出应用程序接口
主要讲解每种外设的程序应该提供哪些接口(系统调用
)
这一层是设备
独立性软件
给用户I/O软件提供的接口
- 按照使用特性分类,设备可以分为字符设备,块设备,网络设备,提供的接口(系统调用)如下
由于不同类型的设备特性不同(比如块设备可以寻址,字符设备不可寻址),因此需要提供不同的系统调用
设备类型 | 提供的接口 | 自己的补充 |
---|---|---|
字符设备接口 | get/put 系统调用:向字符设备读/写一个字符 |
字符接口设备没有地址而言 C语言的scanf和printf应该掉用了get和put系统调用 |
块设备接口 | read/write 系统调用:向块设备的读写指针位置读/写多个字符 seek 系统调用:修改读写指针位置 |
C语言中的fseek函数仅仅是库函数,实际上调用的是seek接口 |
网络设备接口 | socket :系统调用︰创建一个网络套接字,需指明网络协议(TCP/UDP)bind :将套接字绑定到某个本地“端口”connect :将套接字连接到远程地址read/write :从套接字读/写数据 |
接下来我们讲解网络设备接口的系统调用的使用流程
![]() |
![]() |
---|
- 内核空间中绿色的部分相当于设备独立性软件管理的缓冲区
- 阻塞l/O:应用程序发出l/O系统调用,进程需转为阻塞态等待。eg:字符设备接口――从键盘读一个字符get(比如C程序中调用scanf函数)
- 非阻塞I/O:应用程序发出I/O系统调用,系统调用可迅速返回,进程无需阻塞等待。eg:块设备接口――往磁盘写数据write
5.7.2 设备驱动程序接口
设备驱动程序要提供给设备独立性软件接口
若各公司开发的设备驱动程序接口不统一,则操作系统很难调用设备驱动程序
- 操作系统
规定好设备驱动程序的接口标准
,各厂商必须按要求开发设备驱动程序
- 不同时操作系统,对设备驱动程序接口的标准各不相同。
- 设备
厂商必须根据操作系统的接口要求
,开发相应的设备驱动程序
,设备才能被使用 - 如下,一个厂商为不同的操作系统提供了接口(是因为两个操作系统规定的接口不一样)
5.8 I/O软件层次(设备驱动程序)
- 设备驱动程序主要负责对硬件设备的具体控制,将
上层发出的一系列命令(如read/write)转化成特定设备“能听得懂”的一系列操作
。包括设置设备寄存器
;检查设备状态
等 - 不同的I/O设备有不同的硬件特性,具体细节只有设备的厂家才知道。因此厂家需要根据设备的硬件特性设计并提供相应的驱动程序。
注:驱动程序一般会以一个独立进程的方式存在。
思考:为什么不同类型的I/O设备需要有不同的驱动程序处理?
各式各样的设备,外形不同,其内部的电子部件(I/O控制器)也有可能不同
比如
佳能打印机 | 惠普打印机 |
---|---|
![]() |
![]() |
- 比较区别,可能寄存器的数量和表示的信息是不一样的
- 佳能打印机的厂家规定状态寄存器为0代表空闲,1代表忙碌。有两个数据寄存器
- 惠普打印机的厂家规定状态寄存器为1代表空闲,0代表忙碌。有一个数据寄存器
不同设备的内部硬件特性也不同,这些特性只有厂家才知道,因此厂家须提供与设备相对应的驱动程序
,CPU执行驱动程序的指令序列
,来完成设置设备寄存器,检查设备状态等工作
鼠标或者键盘第一次插入电脑的时电脑右下角会有一个正在安装驱动程序的提示,这就是在安装这个IO:驱动程序
5.9 I/O软件层次(中断处理程序)
当I/O任务完成时,I/O控制器会发送一个中断信号
,系统会根据中断信号类型找到相应的中断处理程序并执行
。中断处理程序的处理流程如下:
可见,中断处理程序也会和硬件直接打交道
总结
- 理解并记住I/O软件各个层次之间的顺序
- 要能够推理判断某个处理应该是在哪个层次完成的(最常考的是设备独立性软件、设备驱动程序这两层。只需理解一个特点即可
- 直接涉及到硬件具体细节、且与中断无关的操作肯定是在设备驱动程序层完成的
- 没有涉及硬件的、对各种设备都需要进行的管理工作都是在设备独立性软件层完成的)