目录
5.5 与设备无关的 I/O 软件
设备独立性:应用程序中所用的设备,不局限于使用某个具体的物理设备。
由于为每个设备所配置的设备驱动程序是与硬件紧密相关的软件,因此为了实现设备独立性,必须再在设备驱动程序之上设置一层软件,称为与设备无关的 I/O 软件。
5.5.1 基本概念
为了实现设备独立性而引入了 逻辑设备 和 物理设备 这两个概念。
- 在应用程序中,使用逻辑设备名称来请求使用某类设备
- 系统在实际执行时,仍然必须使用物理设备名称
因此,系统必须具有将逻辑设备名称转换为某个物理设备名称的功能。
逻辑设备名称是抽象的设备名称,如 /dev/printer,该设备名称只是说明用户需要使用打印机来打印输出,但并没有指定具体是哪一台打印机。
实现设备独立性的好处:
① 设备分配时的灵活性:进程能以逻辑设备名称来请求使用某类设备。系统可立即将该类设备中未被分配的任意一个分配给进程,仅当所有该类设备已全部分配完毕时,进程才会被阻塞。
分配时需要使用银行家算法避免死锁
② 易于实现 I/O 重定向:I/O 重定向是指用于 I/O 操作的设备可以更换,而不必改变应用程序。
只要修改逻辑设备表即可
5.5.2 与设备无关的软件的功能
与设备无关的软件是 I/O 系统的最高层软件
1. 执行所有设备的公有操作
- 对独立设备的分配与回收
- 将逻辑设备名映射为物理设备名,进一步查找相应的设备驱动程序
- 对设备进行保护,禁止用户直接访问设备
- 缓冲管理,即对字符设备和块设备的缓冲区进行有效的管理
- 差错控制
设备映射表中含有设备驱动程序的首地址
2. 向用户层软件提供统一接口
无论何种设备,它们向用户所提供的接口应该是相同的:
- 对各种设备的读操作,在应用程序中都使用 read
- 对各种设备的写操作,在应用程序中也都使用 write
5.5.3 设备分配
在多道程序环境下,系统中的设备被所有进程共享,为防止进程对系统资源的无序竞争,必须由系统统一分配设备。除此之外,为了确保 CPU 与设备之间能够进行通信,还应分配相应的设备控制器和通道。
1、设备分配中的数据结构
为实现设备分配,系统中应设置相应的数据结构
① 设备控制表 DCT:系统为每一个设备都配置了一张设备控制表,用于记录设备的情况。
- 指向控制器表的指针:指向该设备连接的设备控制器们的控制表 COCT 的指针
- 设备队列的队首指针:指向请求该设备而未被满足的进程 PCB 们的设备请求队列的指针
② 控制器控制表、通道控制表和系统设备表
- COCT:为每个设备控制器配置一张表,它反映控制器的使用状态。
- CHCT:为每个通道配置一张表,它反映通道的使用状态。
- SDT:记录已被连接到系统中的所有物理设备的情况。
每个物理设备占一个表目,整个系统配置一张 SDT
2、设备分配过程
3、设备分配时应考虑的因素
① 设备的固有属性
- 独占性:在一段时间内,该设备只允许一个进程独占,即是临界资源。
- 共享性:在一段时间内,该设备允许多个进程共享。
- 可虚拟性:虚拟设备是利用某种技术把独占设备改造成可由多个进程共享的设备。
② 设备分配算法
- 先来先服务
- 优先级高者优先
I/O 设备速率慢 && 切换进程开销大 => 算法花样没有那么多
③ 设备分配中的安全性
安全分配方式:
- 每当进程发出 I/O 请求后,便进入阻塞状态,I/O 操作完成后唤醒
- 摒弃了 “请求和保持” 条件,不会产生死锁
- 缺点:进程进展缓慢,即 CPU 与 I/O 设备串行工作
不安全分配方式:
- 进程发出 I/O 请求后仍继续运行
- 可操作多个设备,推进迅速
- 缺点:不安全,具备 “请求和保持” 条件,可能死锁
4、设备分配程序的改进
① 基本分配程序的问题
- 进程以物理设备名提出 I/O 请求,无设备独立性
- 采用单通路 I/O 系统结构,容易产生瓶颈
② 改进方案
- 增加设备独立性
- 考虑多通路情况
增加通道的代价太大
5.5.4 逻辑设备名到物理设备名映射的实现
1、逻辑设备表 LUT
用于实现将应用程序中的逻辑设备名映射为物理设备名。
方法一:在整个系统中只设置一张 LUT 。由于系统中所有进程的设备分配情况都记录在同一张 LUT 中,因而不允许 LUT 中具有相同的逻辑设备名,这就要求所有用户都不使用相同的逻辑设备名。在多用户环境下这通常是难以做到的,因而这种方式主要用于单用户系统中。
方法二:为每个用户设置一张 LUT 。每当用户登录时,系统便为该用户建立一个进程,同时也为之建立一张 LUT,并将该表放入进程的 PCB 中。由于通常在多用户系统中都配置了系统设备表,故此时的逻辑设备表可以采用图 b 的形式。
“系统设备表指针” 应该就是数组下标吧(?)
物理设备名是 OS 分配的,因此在不同 OS 中同一物理设备的物理设备名可能不同。
2、逻辑设备表的修改
可见逻辑设备名保持不变,因此我们编写的程序也不用修改
Q:tty1 和 tty2?
当进程用逻辑设备名请求分配 I/O 设备时,系统根据当时的具体情况,为它分配一台相应的物理设备。与此同时,在逻辑设备表上建立一个表目,填上应用程序中使用的逻辑设备名和系统分配的物理设备名,以及该设备驱动程序的入口地址。当以后进程利用该逻辑设备名请求 I/O 操作时,系统通过查找 LUT,便可找到该逻辑设备所对应的物理设备和该设备的驱动程序。
5.6 用户层的 I/O 软件
由于大部分 I/O 软件都在 OS 内部,只有一小部分在用户层。因此,用户程序必须通过一组系统调用来取得 OS 服务。此外,现代高级语言通常提供了与各系统调用对应的库函数,因此用户程序也可以通过调用对应的库函数来使用系统调用。
5.6.1 系统调用与库函数
1、系统调用
2、库函数(Win32 API)
5.6.2 假脱机技术 SPOOLing
1、虚拟设备技术
虚拟设备技术:将一台物理 I/O 设备虚拟为多台逻辑 I/O 设备。
虚拟性是 OS 的四大特征之一。多道程序技术将一台物理 CPU 虚拟为多台逻辑 CPU,从而允许多个用户共享一台主机。而 SPOOLing 技术将一台物理 I/O 设备虚拟为多台逻辑 I/O 设备,这样也就允许多个用户共享一台物理 I/O 设备。
采用 SPOOLing 技术实现虚拟设备技术
2、SPOOLing 技术
在 OS 引入多道程序技术之后,完全可以利用其中一道程序来模拟外围 I/O 处理机的功能,以完成对设备的 I/O 操作。这样,便可在主机的直接控制下,实现以前的脱机输入、输出功能。因为是 “在主机的直接控制下”,所以又称为假脱机技术。
SPOOLing 技术
在主机的直接控制下,实现脱机输入、输出功能,此时的外围操作与 CPU 对数据的处理同时进行。把这种在联机情况下实现的同时外围操作称为 SPOOLing (Simultaneous Periphernal Operating On-Line) 或称为假脱机操作。
用联机的方式来实现脱机输入、输出功能:虽然 I/O 操作由 SPOOLing 程序来负责完成,但是 SPOOLing 程序还是需要 CPU 来运行,因此脱了但没完全脱。
3、SPOOLing 的组成
SPOOLing 系统主要由以下四部分组成:
- 输入井和输出井
- 输入缓冲区和输出缓冲区
- 输入进程和输出进程
- 井管理程序
井管理程序:当作业执行过程中向某台设备发出启动输入或输出操作请求时,由操作系统调用井管理程序,由其控制(用户进程)从输入井读取信息或(用户进程)将信息输出至输出井。
4、SPOOLing 的处理过程
① 让输入设备输入数据
(1)从输入设备到输入井
- 用户进程 a 请求让输入设备输入数据
- 输入进程为 a 在输入井中分配空间
- 输入设备向输入缓冲区输入数据,再存放到输入井中
- 同时生成 输入请求表 挂入 输入请求队列
(2)从输入井到用户进程
- 当 CPU 空闲时,从 输入请求队列 中取出一张 输入请求表
- 根据其中任务,将设备数据送入内存中相应用户进程的缓冲区
输入请求队列:
② 让输出设备输出数据:打印
(1)从用户进程到输出井
- 用户进程 b 请求向输出设备输出数据
- 输出进程为 b 在输出井中分配空间
- 把用户进程的数据存放到输出井中
- 同时生成 打印请求表 挂入 打印请求队列
(2)从输出井到输出设备
- 当打印机空闲时,从 打印请求队列 中取出一张 打印请求表
- 根据其中任务,将输出井中的相应数据送入输出缓冲区,再由打印机打印