操作系统-I/O管理
I/O管理
I/O 系统
I/O 系统是 OS 的重要组成部分,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设备进行控制
|
目前对 I/O 设备有四种控制方式:采用轮询的可编程 I/O 方式、采用中断的可编程 I/O 方式、直接存储器访问方式、I/O 通道方式
|
确保对设备的正确共享
|
进程应互斥地访问独占设备,共享设备可以在一段时间内允许多个进程同时访问
|
错误处理
|
低层软件能够解决的错误就不向上层报告,只有低层软件解决不了的错误才向上层报告,请求高层软件解决
|
I/O软件层次
- 用户进程层执行输入输出系统调用,对I/O数据进行格式化,为假脱机输入输出做准备。实现与用户交互的接口,用户可以直接调用该层提供的库函数对设备进行操作
- 独立于设备的软件实现用户程序与设备驱动器的统一接口、设备命名、设备的保护以及设备的分配与释放等,为设备管理和数据传送提供必要的存储空间
- 设备驱动程序设置设备寄存器、检查设备的执行状态,用于具体实现系统对设备发出的操作指令,驱动 I/O 设备工作的驱动程序
- 中断处理程序负责I/O完成时,唤醒设备驱动程序进程,进行中断处理,用于保存被中断进程的 CPU 环境,转入相应的中断处理程序进行处理,处理完毕再恢复被中断进程的现场后,返回到被中断的进程
- 硬件层面实现物理I/O的操作
I/O 系统模型
与前面所述的 I/O 软件组织的层次结构相对应,I/O 系统本身也可分为三个层次。
层次
|
说明
|
中断处理程序
|
处于 I/O 系统的底层,直接与硬件进行交互。当有 I/O 设备发来中断请求信号时,中断处理程序首先保存被中断进程的 CPU 环境,然后转入相应设备的中断处理程序进行处理,在处理完成后又恢复被中断进程的 CPU 环境,返回断点继续运行
|
设备驱动程序
|
处于 I/O 系统的次底层,是进程和设备控制器之间的通信程序,将上层发来的抽象 I/O 请求转换为对 I/O 设备的具体命令和参数,并把它装入到设备控制器中的命令和参数寄存器中
|
设备独立性软件
|
实现了与设备无关性,内容包括设备命名、设备分配、数据缓冲和数据高速缓冲一类软件等
|
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011224134831-1861229345.png)
由于设备之间的差异很大,每类设备的驱动程序都不相同,故必须由设备制造厂商提供。每当在系统中增加一个新设备时,都需要由安装厂商提供新的驱动程序。这些层次之间有 I/O 系统接口和软件/硬件接口。
接口
|
说明
|
I/O 系统接口
|
I/O 系统与上层系统之间的接口,向上层提供对设备进行操作的抽象 I/O 命令,一些 OS 在用户层提供了与 I/O 操作有关的库函数
|
软件/硬件(RW/HW)接口
|
在它的上面是中断处理程序和用于不同设备的设备驱动程序,在它的下面是各种设备的控制器
|
I/O 系统接口
在 I/O 系统与高层之间的接口中,根据设备类型的不同,又进一步分为若干个接口,例如块设备接口、流设备接口和网络接口。
块设备接口
块设备接口是块设备管理程序与高层之间的接口,用于控制该类设备的输入或输出。块设备是指数据的存取和传输都是以数据块为单位的设备,典型的块设备是磁盘。该设备的基本特征是传输速率较高,并且可寻址。块设备接口将磁盘上的所有扇区从 0 到 n-1 依次编号,n 是磁盘中的扇区总数。这样编号后把磁盘的二维结构改变为一种线性序列,使块设备接口隐藏了磁盘地址是二维结构的情况。块设备接口支持上层发来的对文件或设备的打开、读、写和关闭等抽象命令,将上述命令映射为设备能识别的较低层具体操作。
虚拟存储器系统也需要使用块设备接口,因为在进程运行期间若所访问的页面不在内存时会发生缺页中断,此时就需要利用 I/O 系统,通过块设备接口从磁盘存储器中将所缺之页面调入内存。
流设备接口
流设备接口是流设备管理程序与高层之间的接口,用于控制字符设备的输入或输出。字符设备指数据的存取和传输是以字符为单位的设备,如键盘、打印机等,基本特征是传输速率较低,并且不可寻址,因而对它只能采取顺序存取方式,用户程序获取或输出字符的方法是采用 get 和 put 操作。由于大多数流设备都属于独占设备,必须采取互斥方式实现共享,为此流设备接口提供了打开和关闭操作。
网络通信接口
在现代 OS 中都提供了面向网络的功能,首先需要通过某种方式把计算机连接到网络上,同时操作系统也必须提供相应的网络软件和网络通信接口,使计算机能通过网络与网络上的其它计算机进行通信或上网浏览。
中断处理程序
中断处理程序又被称为中断服务程序 或者是 ISR(Interrupt Service Routines),它是最靠近硬件的一层。中断处理程序由硬件中断、软件中断或者是软件异常启动产生的中断,用于实现设备驱动程序或受保护的操作模式(例如系统调用)之间的转换。中断在操作系统是多道程序得以实现的基础,,因为进程之间的切换是通过中断来完成的。中断也是设备管理的基础,为了提高处理机的利用率和实现 CPU 与 I/O 设备并行执行,也必需有中断的支持。
中断处理程序负责处理中断发生时的所有操作,操作完成后阻塞,然后启动中断驱动程序来解决阻塞。通常会有三种通知方式,依赖于不同的具体实现
- 信号量实现中:在信号量上使用 up 进行通知;
- 管程实现:对管程中的条件变量执行 signal 操作
- 还有一些情况是发送一些消息
不管哪种方式都是为了让阻塞的中断处理程序恢复运行。
中断和陷入
中断是指 CPU 对 I/O 设备发来的中断信号的一种响应,CPU 暂停正在执行的程序,保留 CPU 环境后,自动地转去执行该 I/O 设备的中断处理程序。执行完后再回到断点,继续执行原来的程序。I/O 设备可以是字符设备,也可以是块设备、通信设备等。由于中断是由外部设备引起的,故又称外中断。
另外还有一种由 CPU 内部事件所引起的中断,通常把这类中断称为内中断或陷入(trap)。若系统发现了有陷入事件,CPU 也将暂停正在执行的程序,转去执行该陷入事件的处理程序。中断和陷入的主要区别是信号的来源,即是来自 CPU 外部还是 CPU 内部。
中断向量表
为了处理上的方便,通常是为每种设备配以相应的中断处理程序,并把该程序的入口地址放在中断向量表的一个表项中。每一个设备的中断请求规定一个中断号,它直接对应于中断向量表的一个表项中。当 I/O 设备发来中断请求信号时,由中断控制器确定该请求的中断号,根据中断号去查找中断向量表取得中断处理程序的入口地址。经常会有多个中断信号源,每个中断源对服务要求的紧急程度并不相同,为此系统就需要为它们分别规定不同的优先级。
中断处理方案有很多种
- 非嵌套的中断处理程序按照顺序处理各个中断,非嵌套的中断处理程序也是最简单的中断处理
- 嵌套的中断处理程序会处理多个中断而无需分配优先级
- 可重入的中断处理程序可使用优先级处理多个中断
- 简单优先级中断处理程序可处理简单的中断
- 标准优先级中断处理程序比低优先级的中断处理程序在更短的时间能够处理优先级更高的中断
- 高优先级 中断处理程序在短时间能够处理优先级更高的任务,并直接进入特定的服务例程。
- 优先级分组中断处理程序能够处理不同优先级的中断任务
下面是一些通用的中断处理程序的步骤,不同的操作系统实现细节不一样
- 保存所有没有被中断硬件保存的寄存器(包括PSW)。
- 为中断服务程序设置上下文环境,可能包括设置 TLB、MMU 和页表。
- 为中断服务程序设置栈
- 对中断控制器作出响应,如果不存在集中的中断控制器,则继续响应中断
- 把寄存器从保存它的地方拷贝到进程表中
- 运行中断服务程序,它会从发出中断的设备控制器的寄存器中提取信息
- 操作系统会选择一个合适的进程来运行。如果中断造成了一些优先级更高的进程变为就绪态,则选择运行这些优先级高的进程
- 为进程设置 MMU 上下文,可能也会需要 TLB,根据实际情况决定
- 加载进程的寄存器,包括 PSW 寄存器
- 开始运行新的进程
由此可见, 中断处理远不是无足轻重的小事。 它要花费相当多的CPU指令, 特别是在存在虚拟内存并且必须设置页表或者必须保存MMU状态(例如R和M位) 的机器上。 在某些机器上, 当在用户态与核心态之间切换时, 可能还需要管理TLB和CPU高速缓存, 这就要花费额外的机器周期。
设备驱动程序
它是 I/O 系统的高层与设备控制器之间的通信程序。其主要任务是接收上层软件发来的抽象 I/O 要求,再把它转换为具体要求后,发送给设备控制器启动设备执行。同时它也将由设备控制器发来的信号传送给上层软件。
设备驱动程序通常位于操作系统其余部分的下面, 如图5-12所示。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011224555352-194116670.png)
设备驱动程序的功能
为了实现 I/O 系统的高层与设备控制器之间的通信,设备驱动程序应具有以下功能:
- 接收由与设备无关的软件发来的命令和参数,并将命令中的抽象要求转换为与设备相关的低层操作序列。
- 检查用户 I/O 请求的合法性,了解 I/O 设备的工作状态,传递与 I/O 设备操作有关的参数,设置设备的工作方式。
- 发出 I/O 命令,如果设备空闲便立即启动 I/O 设备并执行,如果设备忙碌则将请求者的请求块挂在设备队列上等待。
- 及时响应由设备控制器发来的中断请求,并根据其中断类型,调用相应的中断处理程序进行处理。、
设备驱动程序的特点
设备驱动程序属于低级的系统例程,它与一般的应用程序及系统程序之间有下述明显差异:
- 实现在与设备无关的软件和设备控制器之间通信和转换的程序;
- 对于不同类型的设备,应配置不同的驱动程序,但可以为相同的多个终端设置终端驱动程序。
- 驱动程序与 I/O 设备所采用的 I/O 控制方式紧密相关;
- 其中的一部分必须用汇编语言书写,目前很多驱动程序的基本部分固化在 ROM 中;
- 一个正在运行的驱动程序常会在一次调用完成前被再次调用。
设备处理方式
在不同的操作系统中,所采用的设备处理方式并不完全相同。设备处理方式分成以下三类,目前来说第三类用的比较多。
- 为每一类设备设置一个进程,专门用于执行这类设备的 I/O 操作;
- 在整个系统中设置一个 I/O 进程,专门用于执行系统中所有各类设备的 I/O 操作;
- 不设置专门的设备处理进程,而只为各类设备设置相应的设备驱动程序,供用户或系统进程调用。
设备驱动程序的处理过程
- 典型的驱动程序在启动时要检查输入参数, 检查输入参数的目的是搞清它们是否是有效的, 如果不是, 则返回一个错误。 如果输入参数是有效的, 则可能需要进行从抽象事项到具体事项的转换。 对磁盘驱动程序来说, 这可能意味着将一个线性的磁盘块号转换成磁盘几何布局的磁头、 磁道、 扇区和柱面号。
- 接着, 驱动程序可能要检查设备当前是否在使用。 如果在使用, 请求将被排入队列以备稍后处理。 如果设备是空闲的, 驱动程序将检查硬件状态以了解请求现在是否能够得到处理。 在传输能够开始之前, 可能需要接通设备或者启动马达。 一旦设备接通并就绪, 实际的控制就可以开始了。
- 控制设备意味着向设备发出一系列命令。 依据控制设备必须要做的工作, 驱动程序处在确定命令序列的地方。 驱动程序在获知哪些命令将要发出之后, 它就开始将它们写入控制器的设备寄存器。 驱动程序在把每个命令写到控制器之后, 它可能必须进行检测以了解控制器是否已经接收命令并且准备好接收下一个命令。这一序列继续进行, 直到所有命令被发出。 对于某些控制器, 可以为其提供一个在内存中的命令链表, 并且告诉它自己去读取并处理所有命令而不需要操作系统提供进一步帮助。
- 命令发出之后, 会牵涉两种情形之一。 在多数情况下, 设备驱动程序必须等待, 直到控制器为其做某些事情, 所以驱动程序将阻塞其自身直到中断到来解除阻塞。 然而, 在另外一些情况下, 操作可以无延迟地完成, 所以驱动程序不需要阻塞。 在字符模式下滚动屏幕只需要写少许字节到控制器的寄存器中, 由于不需要机械运动, 所以整个操作可以在几纳秒内完成, 这便是后一种情形的例子。在前一种情况下, 阻塞的驱动程序可以被中断唤醒。 在后一种情况下, 驱动程序根本就不会休眠。 无论是哪一种情况, 操作完成之后驱动程序都必须检查错误。 如果一切顺利, 驱动程序可能要将数据(例如刚刚读出的一个磁盘块) 传送给与设备无关的软件。
- 最后, 它向调用者返回一些用于错误报告的状态信息。 如果还有其他未完成的请求在排队, 则选择一个启动执行。 如果队列中没有未完成的请求, 则该驱动程序将阻塞以等待下一个请求。
这一简单的模型只是现实的粗略近似, 许多因素使相关的代码比这要复杂得多。 首先, 当一个驱动程序正在运行时, 某个I/O设备可能会完成操作, 这样就会中断驱动程序。 中断可能会导致一个设备驱动程序运行, 事实上, 它可能导致当前驱动程序运行。 例如, 当网络驱动程序正在处理一个到来的数据包时, 另一个数据包可能到来。 因此, 驱动程序必须是重入的(reentrant) , 这意味着一个正在运行的驱动程序必须预料到在第一次调用完成之前第二次被调用。
在一个热可插拔的系统中, 设备可以在计算机运行时添加或删除。 因此, 当一个驱动程序正忙于从某设备读数据时, 系统可能会通知它用户突然将设备从系统中删除了。 在这样的情况下, 不但当前I/O传送必须中止并且不能破坏任何核心数据结构, 而且任何对这个现已消失的设备的悬而未决的请求都必须适当地从系统中删除, 同时还要为它们的调用者提供这一坏消息。 此外, 未预料到的新设备的添加可能导致内核重新配置资源(例如中断请求线) , 从驱动程序中撤除旧资源, 并且在适当位置填入新资源。
驱动程序不允许进行系统调用, 但是它们经常需要与内核的其余部分进行交互。 对某些内核过程的调用通常是允许的。 例如, 通常需要调用内核过程来分配和释放硬接线的内存页面作为缓冲区。 还可能需要其他有用的调用来管理MMU、 定时器、 DMA控制器、 中断控制器等。
与设备无关的 I/O 软件
为了方便用户和提高 OS 的可适应性与可扩展性,在现代 OS 的 I/O 系统中都增加了与设备无关的 I/O 软件,以实现设备独立性(设备无关性)。其基本含义是:应用程序中所用的设备,不局限于使用某个具体的物理设备。为了实现设备独立性,必须再在设备驱动程序之上设置一层软件,称为与设备无关的 I/O 软件(设备独立性软件)。
图5-13所示的功能典型地由与设备无关的软件实现。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011224741468-1713459268.png)
引入设备独立性软件的动机
在早期 OS 中,应用程序在使用 I/O 设备时都使用设备的物理名称,这使应用程序与系统中的物理设备直接相关。当应用进程运行时,如果所请求的物理设备(独占设备类型)已分配给其它进程,系统无法将另外相同的设备(物理设备名不同)分配给它,致使该应用进程请求 I/O 失败而被阻塞。当应用程序所需要的设备在系统中已经被更新时,该应用程序将再也无法在该系统上运行。可见应用程序直接与物理设备相关是不灵活的,I/O 设备的利用率低。
为了实现与设备的无关性而引入了逻辑设备和物理设备两个概念,逻辑设备是抽象的设备名,并没有指定具体的设备。只要系统中有一台该类设备未被分配,进程就不会被阻塞。与设备的无关软件还可实现 I/O 重定向,是指用于 I/O 操作的设备可以更换,而不必改变应用程序。
与设备无关的软件实现
在与设备无关的软件中,包括了执行所有设备公有操作的软件,具体有如下几项。
功能
|
说明
|
设备驱动程序的统一接口
|
要求每个设备驱动程序与 OS 之间都有着相同或者相近的接口,使添加一个新的设备驱动程序变得很容易
|
缓冲管理
|
为了缓和 CPU 和 I/O 设备之间的速率矛盾,需要为设备配置相应的缓冲区
|
差错控制
|
设备中的机械和电气部分比主机更容易出现故障,因此需要对差错进行处理
|
对独立设备的分配与回收
|
为了避免诸进程对独占设备的争夺,必须由系统来统一分配,不允许进程自行使用
|
独立于设备的逻辑数据块
|
不同类型的设备的数据交换单位和读取、传输速率相同,设备独立性软件应能够隐藏这些差异
|
其中设备的错误可分为如下两类:
设备错误
|
说明
|
暂时性错误
|
因发生暂时性事件引起的,如电源的波动,可以通过重试操作来纠正
|
持久性错误
|
由持久性故障引起的,如电源掉电、磁盘上有划痕或者在计算中发生除以零的情况等
|
设备名映射
当应用程序请求使用 I/O 设备时应当用逻辑设备名。但系统只识别物理设备名,因此在系统中需要配置一张逻辑设备表,用于将逻辑设备名映射为物理设备名。逻辑设备表 LUT(Logical Unit Table)的每个表目中包含了三项:逻辑设备名、物理设备名和设备驱动程序的入口地址。当进程用逻辑设备名请求分配 I/O 设备时,系统为它分配一台相应的物理设备,并在逻辑设备表上建立一个表目。当以后进程再利用该逻辑设备名请求 I/O 操作时,系统通过查找 LUT 可找到该逻辑设备所对应的物理设备和该设备的驱动程序。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011224856271-1987871776.png)
在系统中可采取两种方式设置逻辑设备表,第一种方式是在整个系统中只设置一张 LUT。由于系统中所有进程的设备分配情况都记录在同一张 LUT 中,因而不允许在 LUT 中具有相同的逻辑设备名,在多用户环境下这通常是难以做到的。第二种方式是为每个用户设置一张 LUT,每当用户登录时,系统便为该用户建立一个进程,同时也为之建立一张 LUT 放入进程的 PCB 中。
用户层的 I/O 软件
大部分的 I/O 软件都放在操作系统内部,但仍有一小部分在用户层,其中包括与用户程序链接在一起的库函数和假脱机系统。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225013288-129903342.png)
系统调用
为使诸进程能有条不紊地使用 I/O 设备,且能保护设备的安全性,不允许运行在用户态的应用进程去直接调用运行在核心态(系统态)的 OS 过程。但另一方面,应用进程在运行时,又必须取得 OS 所提供的服务。为了解决此矛盾,OS 在用户层中引入了系统调用,应用程序可以通过它间接调用 OS 中的 I/O 过程。
当应用程序需要执行某种 I/O 操作时,在应用程序中必须使用相应的系统调用。当 OS 捕获到应用程序中的该系统调用后,便将 CPU 的状态从用户态转换到核心态,然后转向操作系统中相应过程,由该过程完成所需的 I/O 操作。执行完成后,系统又将 CPU 状态从核心态转换到用户态,返回到应用程序继续执行。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225047170-669778482.png)
在早期的操作中,系统调用是以汇编语言形式提供的,所以只有在用汇编语言编写的程序中,才能直接使用系统调用。后来在 C 语言中,首先提供了与系统调用相对应的库函数。库函数对于 I/O 方面,主要是对文件和设备进行读/写的库函数,以及控制/检查设备状态的库函数。
假脱机系统
假脱机(SPOOLing)技术,则可将一台物理 I/O 设备虚拟为多台逻辑 I/O 设备,这样就允许多个用户共享一台物理 I/O 设备。SPOOLing 的系统组成如下:
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225112542-1285012626.png)
组成部分
|
说明
|
输入井
|
在磁盘上开辟出来的存储区域,输入井模拟脱机输入时的磁盘,用于收容 I/O 设备输入的数据
|
输出井
|
在磁盘上开辟出来的存储区域,输出井模拟脱机输出时的磁盘,用于收容用户程序的输出数据
|
输入缓冲区
|
在内存上开辟出来的存储区域,用于暂存由输入设备传送的数据,之后再传送到输入井
|
输出缓冲区
|
在内存上开辟出来的存储区域,用于暂存从输出井传送的数据,之后再传送到输出设备
|
输入进程
|
用于模拟脱机输入时的外围控制机,将用户要求的数据从输入设备传送到输入缓冲区
|
输出进程
|
用于模拟脱机输出时的外围控制机,将输出井中的数据经过输出缓冲区输出至输出设备上
|
井管理程序
|
用于控制作业与磁盘井之间信息的交换
|
SPOOLing 系统有以下特点:
- 提高了 I/O 的速度:从对低速 I/O 设备执行的 I/O 操作演变为对磁盘缓冲区中数据的存取;
- 将独占设备改造为共享设备;
- 实现了虚拟设备功能:宏观上虽然是多个进程在同时使用一台独占设备,而对于每一个进程而言,它们都会认为自己是独占了一个设备。
假脱机打印机
打印机是经常用到的输出设备,属于独占设备,利用假脱机技术可将它改造为一台可供多个用户共享的打印设备。假脱机打印系统主要有以下三部分:
部分
|
说明
|
磁盘缓冲区
|
在磁盘上开辟的一个存储空间,用于暂存用户程序的输出数据
|
打印缓冲区
|
设置在内存中,暂存从磁盘缓冲区送来的数据,以后再传送给打印设备进行打印
|
假脱机管理进程
|
为每个要求打印的用户数据建立一个假脱机文件,并把它放入假脱机文件队列中
|
假脱机打印进程
|
依次对队列中的文件进行打印
|
当多个用户进程提出输出打印的请求时,系统会答应它们的请求,但是并不是真正把打印机分配给他们,而是由假脱机管理进程为每个进程做两件事:
- 在磁盘输出井中为进程申请一个空闲缓冲区,并将要打印的数据送入其中;
- 为用户进程申请一张空白的打印请求表,并将用户的打印请求填入表中,再将该表挂到假脱机文件队列上。
由此可见,利用假脱机系统向用户提供共享打印机的概念是:对每个用户而言,系统并非即时执行其程序输出数据的真实打印操作,而只是即时将数据输出到缓冲区,这时的数据并未真正被打印,只是让用户感觉系统已为他打印。真正的打印操作,是在打印机空闲且该打印任务在等待队列中已排到队首时进行的,而且打印操作本身也是利用 CPU 的一个时间片,没有使用专门的外围机。以上的过程是对用户屏蔽的,用户是不可见的。
I/O硬件原理
I/O设备
I/O 就是输入/输出(Input/Output),I/O 设备就是可以将数据输入到计算机,或者可以接收计算机输出数据的外部设备,属于计算机中的硬件部件。I/O 设备一般是由执行 I/O 操作的机械部分和执行控制 I/O 的电子部件组成,I/O 设备的机械部件主要用来执行具体 I/O 操作,例如鼠标/键盘的按钮、显示器的 LED 屏和移动硬盘的磁臂、磁盘盘面。
CPU 无法直接控制 I/O 设备的机械部件,因此 I/O 设备还要有一个电子部件作为 CPU 和 I/O 设备机械部件之间的“中介”,用于实现 CPU 对设备的控制。这个电子部件就是 I/O 控制器,又称设备控制器,通常是一块插入主板扩充槽的印刷电路板。CPU 可控制 I/O 控制器,又由 I/O 控制器来控制设备的机械部件。
I/O设备类型
按数据组织分:
- 块设备:这类设备用于存储信息,信息以数据块为单位,如磁盘,每个盘块512B~4KB,传输速率较高,通常每秒钟几兆位,另一特征是可寻址,即对它可随机地读/写任一块,磁盘设备的I/O常采用DMA方式。
- 字符设备:用于数据的输入和输出,其基本单位是字符,属于无结构类型,如打印机等,其传输速率较低,通常为几个字节至数千个字节,另一特征是不可寻址,即输入/出时不能指定数据的输入源地址及输出的目标地址,此外,常采用中断驱动方式。
按资源分配:
- 独占设备:在一段时间内只允许一个用户(进程)访问的设备,即临界资源。
- 共享设备:在一段时间内允许多个进程同时访问的设备,当然,每一时刻仍然只允许一个进程访问,如磁盘(可寻址和可随机访问)。
- 虚拟设备:通过虚拟技术将一台设备变换为若干台逻辑设备,供若干个用户(进程)同时使用。常用共享设备模拟独占设备,用高速设备模拟低速设备,被模拟的设备称为虚设备。目的:将慢速的独占设备改造为多个用户共享设备,提高设备利用率。例如:spooling技术,利用虚设备技术----用硬盘模拟输入输出设备。
按使用特性分配:
- 存储设备:也称外存、辅存,用以存储信息,存取速度较内存慢但容量大且价格便宜。
- I/O设备:
- 输入设备:用来接收外部信息,如键盘、鼠标、扫描仪、视频摄像等
- 输出设备:用于将计算机处理后的信息送向处理机外部的设备,如打印机、绘图仪等
- 交互式设备:则是指集成的上述两类设备,用于同步显示用户命令以及命令执行的结果
按传输速度分配:
- 低速设备:传输速率仅为每秒钟几个字节至数百个字节,例如键盘、鼠标器
- 中速设备:传输速率在每秒钟数千个字节至数十万个字节,例如行式打印机、激光打印机等
- 高速设备:传输速率在数十万字节至千兆字节,例如磁带机、磁盘机、光盘机等
I/O设备组成
I/O设备一般由机械和电子两部分组成。
- 机械部分是设备本身(物理装置)
- 电子部分又称设备控制器(或适配器)
- (端口)地址译码
- 按照主机与设备之间约定的格式和过程接受计算机发来的数据和控制信号或向主机发送数据和状态信号
- 将计算机的数字信号转换成机械部分能识别的模拟信号,或反之
- 实现设备内部硬件缓冲、数据加工等提高性能或增强功能
设备与控制器之间的接口
通常设备并不是直接与 CPU 进行通信,而是与设备控制器通信,因此在 I/O 设备中应含有与设备控制器间的接口。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225455654-1350248300.png)
在该接口中有三种类型的信号,各对应一条信号线。
信号线
|
说明
|
数据信号线
|
在设备和设备控制器之间传送数据信号
|
控制信号线
|
由设备控制器向 I/O 设备发送控制信号时的通路,信号规定了设备将要执行的操作,如读操作、写操作或执行磁头移动等操作
|
状态信号线
|
该信号线用于传送指示设备当前状态的信号,状态有正在读(或写)、设备已读(写)完成
|
设备控制器
设备控制器是计算机中的一个实体,其主要职责是控制一个或多个I/O设备,以实现I/O设备和计算机之间的数据交换,它是CPU与I/O设备之间的接口,它接收从CPU发来的命令,并去控制I/O设备工作,以使处理从繁杂的设备控制事务中解脱出来。其是一个可编址的设备,当它仅控制一个设备时,它只有一个唯一的设备地址,若控制器可连接多个设备时,则应该含有多个设备地址,并使每个设备地址对应一个设备。每一个设备地址对应一个设备。设备控制器可以分为用于控制字符设备的控制器和用于控制块设备的控制器。
设备控制器的基本功能如下
① 接收和识别命令,CPU可以向控制器发送多种不同的命令,设备控制器应能够接收并识别这些命令,为此,控制器中应具有相应的控制寄存器,用来存放接收的命令和参数,并对所接收的命令进行译码,相应的,在磁盘控制器中有多个寄存器和命令译码器。当控制器接受一条命令后,可独立于CPU完成指定操作,CPU可以另外执行其他计算;命令完成时,控制器产生一个中断,CPU响应中断,控制转给操作系统;通过读控制器寄存器中的信息,获得操作结果。
② 数据交换,实现CPU与控制器之间、控制器与设备之间的数据交换,对于前者,通过数据总线,由CPU并行地将数据写入控制器,或从控制器中并行地读出数据,对于后者,是是被将数据输入到控制器,或从控制器传送给设备,为此,在控制器中必须设置一个数据寄存器。
③ 标识和报告设备的状态,控制器应该几下设备的状态供CPU了解,在控制器中设置一状态寄存器,用其中的每一位来反映设备的某一种状态,当CPU将该寄存器的内存读入后,便可了解该设备的状态。
④ 地址识别,系统中的每一个设备都有一个地址,而设备控制器又必须能够识别它所控制的每个设备的地址,此外,为使CPU能向(或从)寄存器中写入(或读出)数据,这些寄存器都应该具有唯一的地址,如硬盘控制器中各寄存器的地址分别为320~32F之一,控制器应该能正确识别这些地址,为此,需要在控制器中配置地址译码器。
⑤ 数据缓冲,由于I/O设备的速率较低而CPU和内存速率很高,故在控制器中必须设置一个缓冲器,在输出时,用此缓冲器暂存由主机高速传来的数据,然后才以I/O设备所具有的速率将缓冲器的数据传送给I/O设备,在输入时,缓冲器则用于暂存从I/O设备送来的数据,待接收一批数据后,再将缓冲器中的数据高速地传送至主机。
⑥ 差错控制,设备控制器监管对I/O设备传送来的数据进行差错检测,若发现传送中出现了错误,则向CPU报告,于是CPU将本次传送的数据作废,并重新传送一次,这样便可以确保数据输入的正确性。
设备控制器的组成
设备控制器位于 CPU 与设备之间,既要与 CPU 通信又要与设备通信,还应具有按照 CPU 所发来的命令去控制设备工作的功能。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225556440-1474805222.png)
组件
|
说明
|
设备控制器与处理机的接口
|
用于实现 CPU 与设备控制器之间的通信,在该接口中共有三类信号线:数据线、地址线和控制线
|
设备控制器与设备的接口
|
设备控制器上可以连接多个设备,便有多个设备接口。在每个接口中都存在数据、控制和状态三种类型的信号
|
I/O 逻辑
|
用于实现对设备的控制,它通过一组控制线与处理机交互,处理机利用该逻辑向控制器发送 I/O 命令。
|
数据线通常与两类寄存器相连接,第一类是数据寄存器,用于存放从设备送来的数据(输入)或从 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端口看作一个存储单元,对I/O的读写操作等同于对内存的操作
优点:
- 凡是可对内存操作的指令都可对I/O端口操作
- 不需要专门的I/O指令
- I/O端口可占有较大的地址空间
缺点:占用内存空间
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225650493-1538210702.png)
内存映像
驱动程序将抽象 I/O 命令转换出的一系列具体的命令、参数等数据装入设备控制器的相应寄存器,由控制器来执行这些命令实施对 I/O 设备的控制。这一工作在早期的计算机中利用特定的 I/O 指令实现,为每个控制寄存器分配一个 I/O 端口并设置了一些特定的 I/O 指令。该方法的主要缺点是,访问内存和访问设备需要两种不同的指令。
现在采用的是内存映像 I/O,这种方式中在编址上不再区分内存单元地址和设备控制器中的寄存器地址,而是设置一个 k 值。当 k 值处于 0 ~ n-1 范围时被认为是内存地址,若 k ≥ n 时被认为是某个控制器的寄存器地址。内存映像 I/O 方式统一了对内存和对控制器的访问方法,简化 I/O 的编程。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225720571-2085672555.png)
内存映射I/O的优点
- 不需要特殊的保护机制来阻止用户进程执行I/O操作;
- 操作系统必须要做的事情:避免把包含控制寄存器的那部分地址空间放入任何用户的虚拟地址空间之中
- 可以引用内存的每一条指令也可以引用控制寄存器
- 例如:如果指令TEST可以测试一个内存字是否为0,那么也可以用来测试一个控制寄存器是否为0
I/O 通道
引入 I/O 通道的动机
虽然在 CPU 与 I/O 设备之间增加了设备控制器后能减少 CPU 对 I/O 的干预,但当主机所配置的外设很多时 CPU 的负担仍然很重。为此在 CPU 和设备控制器之间又增设了I/O 通道(I/O Channel)。主要目的是使一些原来由 CPU 处理的 I/O 任务转由通道来承担,从而把 CPU 从繁杂的 I/O 任务中解脱出来。
在设置了通道后,CPU 只需向通道发送一条 I/O 指令,通道从内存中取出本次要执行的通道程序然后执行。仅当通道完成了规定的 I/O 任务后,才向 CPU 发中断信号。实际上 I/O 通道是一种特殊的处理机,它具有执行 I/O 指令的能力,通过执行通道 I/O 程序来控制 I/ O操作。但 I/O 通道的指令类型单一,且没有自己的内存。
通道类型
外围设备的类型较多,传输速率相差甚大,因而使通道具有多种类型。根据信息交换方式的不同,可把通道分成以下三种类型。
通道
|
说明
|
字节多路通道(Byte Multiplexor Channel)
|
按字节交叉方式工作的通道,通常都含有许多非分配型子通道,按时间片轮转方式共享主通道,当第一个子通道控制其 I/O 设备完成一个字节的交换后,便立即腾出主通道让给第二个子通道使用
|
数组选择通道(Block Selector Channel)
|
按数组方式进行数据传送的数组选择通道,可以连接多台高速设备,但它只含有一个分配型子通道,在一段时间内只能执行一道通道程序
|
数组多路通道(Block Multiplexor Channel)
|
将数组选择通道传输速率高和字节多路通道能使各子通道(设备)分时并行操作的优点相结合,它含有多个非分配型子通道,既具有很高的数据传输速率,又能获得令人满意的通道利用率
|
瓶颈问题
由于通道价格昂贵,致使机器中所设置的通道数量势必较少,这往往又使它成了 I/O 的瓶颈,进而造成整个系统吞吐量的下降。例如在图中如果要使用设备 1 需要占用通道 1 和控制器 1,但此时如果还要使用设备 2,会因为通道和控制器数量不足而无法使用。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225822186-1458953606.png)
解决“瓶颈”的方法是增加设备到主机间的通路而不增加通道,也就是把一个设备连接到多个控制器上,而一个控制器又连接到多个通道上。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225846083-1085597545.png)
I/O控制方式
在 I/O 控制方式的整个发展过程中,始终贯穿着这样一条宗旨:尽量减少主机对 I/O 控制的干预,把主机从繁杂的 I/O 控制事务中解脱。
程序I/O方式(轮询/查询)
在早些计算机系统中,由于无中断机构,处理机对I/O设备的控制采取程序I/O方式,或称为忙-等待方式,即在处理机向控制器发出一条I/O指令启动输入设备输入数据时,要同时把状态寄存器中的忙/闲标志busy设置为1,然后便不断地循环测试busy,只有当其为0时,表示输入已经送入控制器的数据寄存器中,于是处理机将数据寄存器中的数据取出,送入内存指定单元中,这样便完成了一个字(符)的I/O。
在程序I/O方式中,由于CPU的高速性和I/O设备的低速性,致使CPU的绝大部分时间都处于等待I/O设备完成数据I/O的循环测试中,造成对CPU的极大浪费。
中断驱动I/O控制方式
当某进程要启动某个I/O设备工作时,便由CPU向相应的设备控制器发出一条I/O命令,然后立即返回继续执行原来的任务,设备控制器于是按照该命令的要求去控制指定I/O设备,此时,CPU与I/O设备并行操作。一旦数据进入数据寄存器,控制器便通过控制线向CPU发送一个中断信号,由CPU检查输入过程中是否出错,若无错,便由控制器发送取走数据的信号,再通过控制器及数据线将数据写入内存指定单元中。
在I/O设备输入每个数据的过程中,由于无需CPU干预,因而可使CPU与I/O设备并行工作,仅当完成一个数据输入时,才需CPU花费极短的时间去做一些中断处理。
直接存储器访问(DMA)I/O控制方式
虽然中断驱动I/O比程序I/O方式更有效,但是,它仍是以字(节)为单位进行I/O的,每当完成一个字(节)的I/O时,控制器便要向CPU请求一次中断,换言之,采用中断驱动I/O方式时的CPU是以字(节)为单位进行干预的,将这种方式用于块设备的I/O是非常低效的,例如,为了从磁盘读取1KB的数据块,需要中断CPU1K次,为了进一步减少CPU对I/O的干预而引入了直接存储器访问方式DMA (Direct Memory Access),该方式的特点如下
① 数据传输的基本单位是数据块,即在CPU与I/O设备之间,每次传送至少一个数据块。
② 所传送的数据是从设备直接送入内存的,或者相反。
③ 仅在传送一个或多个数据块的开始和结束时,需要CPU干预,整块数据的传送是在控制器的控制下完成的。
当给 I/O 模块发送命令时,CPU 指明此次要进行的操作,并说明要读入多少数据、数据要存放在内存的什么位置数据在外部设备上的地址。控制器会根据 CPU 提出的要求完成数据的读/写工作,整块数据的传输完成后,才向 CPU 发出中断信号。
DMA控制器由三部分组成,主机与DMA控制器的接口;DMA控制器与块设备的接口;I/O控制逻辑。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011225940379-1285122995.png)
说明:DMA控制器中的寄存器说明如下
① 命令/状态寄存器(CR),用于接收从CPU发送来的I/O命令,或有关控制信息,或设备的状态。
② 内存地址寄存器(MAR),在输入时,它存放把数据从设备传送到内存的起始目标地址,在输出时,它存放由内存到设备的内存源地址。
③ 数据寄存器(DR),用于暂存从设备到内存,或从内存到设备的数据。
④ 数据计数器(DC),存放本次CPU要读或写的字(节)数。
当CPU要从磁盘读入一个数据块时,便向磁盘控制器发送一条读命令,该命令被送到其中的命令寄存器(CR)中,同时,还需要发送本次要将数据读入的内存起始目标地址,该地址被送入内存地址寄存器(MAR)中,本次要读数据的字(节)数被送入数据寄存器(DC)中,还须将磁盘中的源地址直接送至DMA控制器的I/O控制逻辑上,然后,启动DMA控制器进行数据传送,以后,CPU便可去处理其他任务,此后,整个数据传送过程便由DMA控制器进行控制,当DMA控制器已从磁盘中读入一个字(节)的数据并送入数据寄存器(DR)后,再挪用一个存储器周期,将该字(节)传送到MAR所指示的内存单元中,接着便对MAR内容加1,将DC内存减1,若减后DC内存不为0,表示传送未完成,便继续传送下一个字(节),否则,由DMA控制发出中断请求。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230005541-1976499756.png)
DMA 的优点是数据传输以“块”为单位,CPU 介入频率进一步降低。数据的传输不再需要先经过C PU 再写入内存,数据传输效率进一步增加,CPU 和 I/O 设备的并行性得到提升。缺点是 CPU 每发出一条 I/O 指令,只能读/写一个或多个连续的数据块。
下图展示了三种不同方式的流程。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230027316-1344729441.png)
I/O 通道控制方式
I/O 通道方式是 DMA 方式的发展,它把对一个数据块的读(或写)为单位的干预,减少为对一组数据块的读(或写)及有关的控制和管理为单位的干预。同时,又可实现 CPU、通道和 I/O 设备三者的并行操作,从而更有效地提高整个系统的资源利用率。不过实现复杂,需要专门的通道硬件支持。
例如当 CPU 要完成一组相关的读(或写)操作及有关控制时,只需向 I/O 通道发送一条 I/O 指令,以给出其所要执行的通道程序的首址和要访问的 I/O 设备。通道接到该指令后,通过执行通道程序便可完成 CPU 指定的 I/O 任务。
设备分配
“设备、控制器、通道”之间的关系是一个通道可控制多个设备控制器,每个设备控制器可控制多个设备。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230145165-1056592136.png)
设备分配中的数据结构
系统为实现对独占设备的分配,必须在系统中配置相应的数据结构,记录了对设备或控制器进行控制所需的信息。系统为每一个设备都配置了一张设备控制表 DCT,用于记录设备的情况。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230210559-1563830143.png)
字段
|
说明
|
设备队列队首指针
|
凡因请求本设备而未得到满足的进程,应将其 PCB 按照一定的策略排成一个设备请求队列
|
忙/闲标志
|
用于表示当前设备的状态是忙或闲
|
与设备连接的控制器表指针
|
指向该设备所连接的控制器的控制表
|
重复执行次数
|
设备在工作中发生错误时应重复执行的次数
|
系统为每一个控制器都设置了用于记录控制器情况的控制器控制表 COCT。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230227827-1166679471.png)
每个通道都有一张通道控制表 CHCT。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230245019-1484685886.png)
系统设备表 SDT 是系统范围的数据结构,记录了系统中全部设备的情况,每个设备占一个表目,其中包括有设备类型、设备标识符、设备控制表及设备驱动程序的入口等项。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230308694-1002376726.png)
独占设备的分配
在申请设备时,,如果设备空闲,就将其独占,不再允许其他进程申请使用,一直等到该设备被释放,才允许被其他进程申请使用。须考虑效率问题,并避免由于不合理的分配策略造成死锁。
静态分配:在进程运行前,完成设备分配;运行结束时,收回设备。缺点:设备利用率低。
动态分配:在进程运行过程中,当用户提出设备要求时,进行分配,一旦停止使用立即收回。优点:效率高;缺点:分配策略不好时,产生死锁。
分时共享设备的分配
分时共享就是以一次I/O为单位分时使用设备,不同进程的I/O操作请求以排队方式分时地占有设备进行I/O。由于同时有多个进程同时访问,就会影响整个设备使用效率,影响系统效率。因此要考虑多个访问请求到达时服务的顺序使平均服务时间越短越好。
设备分配的因素
系统在分配设备时,应考虑如下几个因素:
设备的固有属性
设备的固有属性可分成三种,对它们应采取不同的分配策略:
固有属性
|
说明
|
独占设备的分配策略
|
将一个设备分配给某进程后,便由该进程独占
|
共享设备的分配策略
|
对于共享设备,可同时分配给多个进程使用
|
虚拟设备的分配策略
|
虚拟设备属于可共享的设备
|
设备分配算法
对设备分配的算法,通常只采用以下两种分配算法:
分配算法
|
说明
|
先来先服务
|
根据诸进程对某设备提出请求的先后次序,将这些进程排成一个设备请求队列
|
优先级高者优先
|
将优先级高的进程排在设备队列前面,而对于优先级相同的 I/O 请求,则按先来先服务原则排队
|
设备分配中的安全性
从进程运行的安全性上考虑,设备分配有以下两种方式:
分配方式
|
说明
|
安全分配方式
|
为进程分配一个设备后就将进程阻塞,本次 I/O 完成后才将进程唤醒
|
不安全分配方式
|
进程发出 I/O 请求后,系统为其分配 I/O 设备,之后还可以发出新的 I/O 请求
|
设备分配的步骤
只有设备、控制器、通道三者都分配成功时,这次设备分配才算成功,之后便可启动 I/O 设备进行数据传送。
- 根据进程请求的物理设备名查找 SDT;
- 分配设备,根据 SDT 找到 DCT,若设备忙碌则将进程PCB挂到设备等待队列中,不忙碌则将设备分配给进程;
- 分配控制器,根据 DCT 找到 COCT,若控制器忙碌则将进程PCB挂到控制器等待队列中,不忙碌则将控制器分配给进程;
- 分配通道,根据 COCT 找到 CHCT,若通道忙碌则将进程PCB挂到通道等待队列中,不忙碌则将通道分配给进程。
为获得设备的独立性,进程应使用逻辑设备名请求 I/O。这样系统首先从 SDT 中找出第一个该类设备的 DCT,若该设备忙又查找第二个该类设备的 DCT,仅当所有该类设备都忙时,才把进程挂在该类设备的等待队列上。
缓冲技术
- 解决CPU与I/O设备之间速度不匹配问题:凡是数据到达和离去速度不匹配的地方均可采用缓冲技术
- 提高CPU与I/O设备之间的并行性
- 减少了I/O设备对CPU的中断请求次数,放宽CPU对中断响应时间的要求
缓冲区
缓冲区是一个存储区域,可以由专门的硬件寄存器组成,也可利用内存作为缓冲区。使用硬件作为缓冲区的成本较高,容量也较小,一般仅用在对速度要求非常高的场合(如存储器管理中所用的联想寄存器)一般情况下利用内存作为缓冲区,“设备独立性软件”的缓冲区管理就是要组织管理好这些缓冲区。
引入缓冲区的原因有:
- 缓和 CPU 与 I/O 设备间速度不匹配的矛盾:CPU 的运算速率远远高于 I/O 设备的速率,如果没有缓冲区,在运行时会因为 I/O 设备跟不上 CPU 的速度导致 CPU 停下来等待;
- 减少对 CPU 的中断频率,放宽对 CPU 中断响应时间的限制。随着传输速率的提高,需要配置位数更多的寄存器进行缓冲;
- 解决数据粒度不匹配的问题:生产者所生产的数据粒度比消费者小时,生产者进程可以一连生产多个数据单元的数据。生产者比消费者粒度大时,生产者每次生产的数据消费者可以分几次从缓冲区中取出消费;
- 提高 CPU 和 I/O 设备之间的并行性:生产者在生产了一批数据并将它放入缓冲区后,便可立即去进行下一次的生产。
缓冲区分类
硬缓冲:由硬件寄存器实现(例如:设备中设置的缓冲区)
软缓冲:在内存中开辟了一个空间,用作缓冲区
缓冲区管理:
单缓冲
双缓冲
缓冲池(多缓冲,循环缓冲):统一管理多个缓冲区,采用有界缓冲区的生产者/消费者模型对缓冲池中的缓冲区进行循环使用
单缓冲区
假设某用户进程请求某种块设备读入若干块的数据。若采用单缓冲(Single Buffer)的策略,操作系统会在主存中为其分配一个缓冲区。当缓冲区数据非空时,不能往缓冲区冲入数据,只能从缓冲区把数据传出。当缓冲区为空时可以往缓冲区冲入数据,但必须把缓冲区充满以后,才能从缓冲区把数据传出。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230443914-942901618.png)
假定从磁盘把一块数据输入到缓冲区的时间为 T,OS 将该缓冲区中的数据传送到用户区的时间为 M,CPU 数据处理(计算)的时间为C。由于 T 和 C 是可以并行的,当 T > C 时系统对每一块数据的处理时间为 M + T,反之则为M + C,故可把系统对每一块数据的处理时间表示为 Max(C,T) + M。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230505447-196374565.png)
双缓冲区
由于缓冲区是共享资源,生产者与消费者在使用缓冲区时必须互斥。如果消费者尚未取走缓冲区中的数据,即使生产者又生产出新的数据,也无法将它送入缓冲区,生产者等待。
如果设置了两个缓冲区能解决这一问题,同时可以加快输入和输出速度,提高设备利用率。双缓冲区机制(Double Buffer)也称缓冲对换(Buffer Swapping),在设备输入时先将数据送入第一缓冲区,装满后便转向第二缓冲区。此时操作系统可以从第一缓冲区中移出数据,并送入用户进程,接着由 CPU 对数据进行计算。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230534423-1193250341.png)
在双缓冲时系统处理一块数据的时间可以粗略地认为是 Max(C,T),如果 C < T 可使块设备连续输入,如果 C > T 则可使 CPU 不必等待设备输入。对于字符设备,若采用行输入方式,在 CPU 执行第一行中的命令时,用户可继续向第二缓冲区输入下一行数据。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230600830-31893439.png)
如果在实现两台机器之间的通信时仅为它们配置了单缓冲,那么它们之间在任一时刻只能实现半双工的数据传输。为了实现全双工数据传输,必须在两台机器中都设置两个缓冲区,一个用作发送缓冲区,另一个用作接收缓冲区。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230625039-623338093.png)
环形缓冲区
若两个缓冲区的速度相差甚远,双缓冲的效果则不够理想,不过可以通过缓冲区数量的增加来改善。多缓冲机制可将多个缓冲区组织成环形缓冲区形式,在环形缓冲中包括多个缓冲区,其每个缓冲区的大小相同。
作为输入的多缓冲区可分为三种类型:用于装输入数据的空缓冲区 R、已装满数据的缓冲区 G 以及计算进程正在使用的现行工作缓冲区 C。作为输入的缓冲区可设置三个指针:用于指示计算进程下一个可用缓冲区 G 的指针 Nextg、指示输入进程下次可用的空缓冲区 R 的指针 Nexti,以及用于指示计算进程正在使用的缓冲区 C 的指针 Current。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230654534-1679455342.png)
使用输入循环缓冲,可使输入进程和计算进程并行执行,相应地指针 Nexti 和 Nextg 将不断地沿着顺时针方向移动。这样就可能出现下 Nexti 指针追赶上 Nextg 指针,这意味着输入进程输入数据的速度大于计算进程处理数据的速度。也有可能出现 Nextg 指针追赶上 Nexti 指针,这意味着输入数据的速度低于计算进程处理数据的速度。
缓冲池
当系统较大时会存在大量的循环缓冲,这不仅要消耗大量的内存空间,而且其利用率不高。目前广泛流行既可用于输入又可用于输出的公用缓冲池,在池中设置了多个可供若干个进程共享的缓冲区。缓冲池与缓冲区的区别在于,缓冲区仅仅是一组内存块的链表,而缓冲池则是包含了一个管理的数据结构及一组操作函数的管理机制。
缓冲池管理着多个缓冲区,每个缓冲区由用于标识和管理的缓冲首部以及用于存放数据的缓冲体两部分组成。缓冲首部一般包括缓冲区号、设备号、设备上的数据块号、同步信号量以及队列链接指针等。为了管理上的方便,一般将缓冲池中具有相同类型的缓冲区链接成一个队列,于是可形成以下三个队列。除了三个队列外,还应具有四种工作缓冲区:用于收容输入数据的工作缓冲区、用于提取输入数据的工作缓冲区、用于收容输出数据的工作缓冲区,以及用于提取输出数据的工作缓冲区。
队列
|
说明
|
空白缓冲队列 emq
|
由空缓冲区所链成的队列
|
输入队列 inq
|
由装满输入数据的缓冲区所链成的队列
|
输出队列 outq
|
由装满输出数据的缓冲区所链成的队列
|
缓冲区可以有如下 4 个工作方式:
- 输入进程请求输入数据;
- 计算进程想要取得一块输入数据;
- 计算进程想要将准备好的数据冲入缓冲区;
- 输出进程请求输出数据。
![](https://img2020.cnblogs.com/blog/1708060/202110/1708060-20211011230741809-779928102.png)
I/O性能问题
- 利用缓冲技术解决CPU与I/O设备之间速度不匹配问题
- 利用异步I/O使CPU不等待I/O
- 利用DMA和通道让CPU摆脱I/O操作
windows提供了两种模式的I/O
- 异步:应用程序启动I/O操作,然后再I/O请求执行的同时继续处理
- 系统实现:
- 通过切换进程保证CPU利用率
- 对少量数据的I/O操作会引入切换的开销
- 用户实现:
- 将访问控制分成两段进行
- 发出读取指令后继续做其他操作
- 当需要用读入的数据的时候,在使用wait命令等待其完成
- 不引入线程切换,减少开销
- 同步:应用程序被阻塞直到I/O操作完成