用户层软件
I/O系统接口
设备独立性(无关性)软件
设备驱动程序
中断处理程序
RW/HW接口
设备控制器
在上、下两个接口之间则是I/O系统
它是I/O系统与上层系统之间的接口,向上层提供对设备进行操作的抽象I/O命令,以方便高层对设备的使用。
有不少OS在用户层提供了与I/O操作有关的库函数,供用户使用。
在上层系统中有文件系统、虚拟存储器系统以及用户进程等。
包括:
块设备接口
流设备接口
网络通信接口
该接口是软件/硬件接口,在它的上面是中断处理程序和用于不同设备的设备驱动程序。
在它的下面是各种设备的控制器。
如CD-ROM控制器、硬盘控制器、键盘控制器、打印机控制器、网络控制器等,它们都属于硬件。
由于设备种类繁多,故该接口相当复杂。
与前面所述的I/O软件组织的层次结构相对应,I/O系统本身也可分为如下三个层次:
(1)中断处理程序。
(2)设备驱动程序。
(3)设备独立性软件。
现代OS中的I/O系统基本上都实现了与设备无关性,也称为与设备无关的软件。
其基本含义是:I/O软件独立于具体使用的物理设备。
由此带来的最大好处是,提高了I/O系统的可适应性和可扩展性。
使它们能应用于许多类型的设备,而且在每次增加新设备或替换老设备时,都不需要对I/O软件进行修改,这样就方便了系统的更新和扩展。
设备独立性软件的内容包括设备命名、设备分配、数据缓冲和数据高速缓冲一类软件等。
由于设备控制器位于CPU与设备之间,它既要与CPU通信,又要与设备通信,还应具有按照CPU所发来的命令去控制设备工作的功能,因此,现有的大多数控制器都是由以下三部分组成:
左半部分是cpu与(设备)控制器的结构结构模型;
中间部分是IO逻辑模块
右半部分是控制器与各个设备接口的结构模型
他们通过IO逻辑模块联系起来(通过IO逻辑实现对设备的控制)
在不同的操作系统中,所采用的设备处理方式并不完全相同。根据在设备处理时是否设置进程,以及设置什么样的进程,而把设备处理方式分成以下三类:
在早期OS中,应用程序在使用I/O设备时,都使用设备的物理名称,这使应用程序与系统中的物理设备直接相关。
当应用进程运行时,如果所请求的物理设备(独占设备类型)己分配给其它进程,而此时尽管还有几台其它的相同设备空闲可用,但系统只能根据设备的物理名来分配,无法将另外相同的设备(但具有不同的物理设备名)分配给它,致使该应用进程请求I/O失败而被阻塞。
特别是,当应用程序所需要的设备在系统中已经被更新时,该应用程序将再也无法在该系统上运行。
可见,应用程序直接与物理设备相关是非常不灵活的,给用户带来了很大的不便,且对提高I/O设备的利用率也很不利。
系统为每一个设备都配置了一张设备控制表,用于记录设备的情况,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVovXoyj-1668646686087)(https://s2.loli.net/2022/06/05/ObHq6IpzrcDlZJW.png)]
其中,设备控制器表对应一个设备控制器,(因此,在后面提到的分配控制器的步骤中),可以从DCT中找出该设备连接的控制器的COCT
设备控制表中,除了有用于指示设备类型的字段type和设备标识字段deviceid外,
还应含有下列字段:
1)基本的设备分配程序
我们通过一个例子来介绍设备分配过程。当某进程提出I/O请求后,系统的设备分配程序可按下述步骤进行设备分配:
(1)分配设备。
首先根据I/O请求中的物理设备名查找系统设备表SDT,从中找出该设备的DCT,
再根据DCT中的设备状态字段,可知该设备是否正忙。
若忙,便将请求I/O的进程的PCB挂在设备队列上;
否则,便按照一定的算法,计算本次设备分配的安全性。
如果不会导致系统进入不安全状态,便将设备分配给请求进程;
否则,仍将其PCB插入设备等待队列。
(2)分配控制器。
在系统把设备分配给请求I/O的进程后,
再到其DCT中找出与该设备连接的控制器的COCT,
从COCT的状态字段中可知该控制器是否忙碌。
若忙,便将请求I/O进程的PCB,挂在该控制器的等待队列上。
否则,便将该控制器分配给进程。
(3)分配通道。
在该COCT中又可找到与该控制器连接的通道的CHCT,
再根据CHCT内的状态信息可知该通道是否忙碌。
- 只有在设备、控制器和通道三者都分配成功时,这次的设备分配才算成功。
- 然后,便可启动该I/O设备进行数据传送。
2)设备分配程序的改进
用户层的I/O软件一般而言,大部分的I/O软件都放在操作系统内部,但仍有一小部分在用户层,其中包括与用户程序链接在一起的库函数,以及完全运行于内核之外的假脱机系统等。
在C语言以及UNIX系统中,系统调用(如read)与各系统调用所使用的库函数(如read)之间几乎是一一对应的。
而微软定义了一套过程,称为Win32API的应用程序接口(ApplicationProgramInterface),程序员利用它们取得OS服务,该接口与实际的系统调用并不一一对应。
用户程序通过调用对应的库函数使用系统调用,这些库函数与调用程序连接在一起,被嵌入在运行时装入内存的二进制程序中。
在C语言中提供了多种类型的库函数,对于I/O方面,主要是对文件和设备进行读/写的库函数,以及控制/检查设备状态的库函数。
显然这些库函数的集合也应是I/O系统的组成部分。
而且我们可以这样来看待内核和库函数之间的关系:内核提供了OS的基本功能,而库函数扩展了OS内核,使用户能方便取得操作系统的服务。
在许多现代OS中,系统调用本身已经采用C语言编写,并以函数形式提供,所以在使用C语言编写的用户程序中,可以直接使用这些系统调用。
另外,操作系统在用户层中还提供了一些非常有用的程序,如下面将要介绍的假脱机系统,以及在网络传输文件时常使用的守护进程等,它们是运行在内核之外的程序,但它们仍属于I/O系统。
如果说,通过多道程序技术可将一台物理CPU虚拟为多台逻辑CPU,从而允许多个用户共享一台主机,那么,通过假脱机技术,则可将一台物理I/O设备虚拟为多台逻辑I/O设备,这样也就允许多个用户共享一台物理I/O设备。
- In computing, spooling is a specialized form of multi-programming for the purpose of copying data between different devices. In contemporary systems,[a] it is usually used for mediating between a computer application and a slow peripheral, such as a printer.
- Spooling allows programs to “hand off” work to be done by the peripheral and then proceed to other tasks, or to not begin until input has been transcribed.
- A dedicated program, the spooler, maintains an orderly sequence of jobs for the peripheral and feeds it data at its own rate.
- Conversely, for slow input peripherals, such as a card reader, a spooler can maintain a sequence of computational jobs waiting for data, starting each job when all of the relevant input is available;
- see batch processing. The spool itself refers to the sequence of jobs, or the storage area where they are held.
- In many cases, the spooler is able to drive devices at their full rated speed with minimal impact on other processing.
Spooling is a combination of buffering and queueing.
Print spooling
Nowadays, the most common use of spooling is printing: documents formatted for printing are stored in a queue at the speed of the computer, then retrieved and printed at the speed of the printer.
Multiple processes can write documents to the spool without waiting, and can then perform other tasks, while the “spooler” process operates the printer.[1]
For example, when a large organization prepares payroll cheques, the computation takes only a few minutes or even seconds, but the printing process might take hours.
If the payroll program printed cheques directly, it would be unable to proceed to other computations until all the cheques were printed.
Similarly, before spooling was added to PC operating systems, word processors were unable to do anything else, including interact with the user, while printing.
Spooler or print management software often includes a variety of related features, such as allowing priorities to be assigned to print jobs, notifying users when their documents have been printed, distributing print jobs among several printers, selecting appropriate paper for each document, etc.
A print server applies spooling techniques to allow many computers to share the same printer or group of printers
- 假脱机技术在20世纪50年代,为了缓和CPU的高速性与I/O设备低速性间的矛盾,而引入了脱机输入、脱机输出技术。
- 该技术是利用专门的外围控制机,先将低速I/O设备上的数据传送到高速磁盘上,或者相反。
打印机是经常用到的输出设备,属于独占设备。利用假脱机技术可将它改造为一台可供多个用户共享的打印设备,从而提高设备的利用率,也方便了用户。
共享打印机技术已被广泛地用于多用户系统和局域网络中。
假脱机打印系统主要有以下三部分:
(1)磁盘缓冲区。它是在磁盘上开辟的一个存储空间,用于暂存用户程序的输出数据,在该缓冲区中可以设置几个盘块队列,如空盘块队列、满盘块队列等。
(2)打印缓冲区。用于缓和CPU和磁盘之间速度不匹配的矛盾,设置在内存中,暂存从磁盘缓冲区送来的数据,以后再传送给打印设备进行打印。
(3)假脱机管理进程和假脱机打印进程。
缓冲区(buffer)是一块内存区域,用于保存在两个设备之间或在设备和应用程序之间传输的数据。
采用缓冲有三个理由。
一个理由是,处理数据流的生产者与消费者之间的速度不匹配。
缓冲的第二种用途是,协调传输大小不一数据的设备。
缓冲的第三种用途是,支持应用程序I/O的复制语义。
由内存组成的缓冲区
由于缓冲区是共享资源,生产者与消费者在使用缓冲区时必须互斥。
如果消费者尚未取走缓冲区中的数据,即使生产者又生产出新的数据,也无法将它送入缓冲区,生产者等待。
如果为生产者与消费者设置了两个缓冲区,便能解决这一问题。
为了加快输入和输出速度,提高设备利用率,人们又引入了双缓冲区机制,也称为缓冲对换(BufferSwapping)
在设备输入时,先将数据送入第一缓冲区,装满后便转向第二缓冲区。
此时操作系统可以从第一缓冲区中移出数据,并送入用户进程
接着由CPU对数据进行计算。
在双缓冲时,系统处理一块数据的时间可以粗略地认为是Max(C+M,T).
如果C+M
如果C+M>T,则可使CPU不必等待设备输入。(比如数据处理比较复杂,是耗时的密集计算,cpu对材料的消耗速度慢于供应速度)
总结:那个慢,那个就不需要等待对方
快的一方则要等待慢的一方
对于字符设备,若采用行输入方式,则采用双缓冲通常能消除用户的等待时间(用户输入慢),即用户在输入完第一行后,在CPU执行第一行中的命令时,用户可继续向第二缓冲区输入下一行数据。
非阻塞系统调用的一种替代方法是异步系统调用。
异步调用立即返回,无需等待I/O完成,应用程序继续执行代码。
在将来I/O完成时,有以下方式来通知应用程序
非阻塞与异步的系统调用的区别是,
One way an application writer can overlap execution with I/O is to writea multithreaded application.
Some threads can perform blocking system calls,while others continue executing.
Some operating systems provide nonblocking I/O system calls.
A nonblocking call does not halt the execution of the application for an extended time.
An alternative to a nonblocking system call is an asynchronous systemcall.
在现代操作系统中,经常发生异步活动。
非阻塞行为的一个很好的例子是,用于网络套接字的系统调用select。
这个系统调用需要一个参数来指定最大等待时间。
通过设置为0,应用程序可以轮流检测网络活动而无需阻塞。
但是采用select引入额外的开销,因为调用select只检查是否可能进行I/O.
对于数据传输,在select()之后,还需要采用某种类型的命令read或write。
在Mach中,有这种方法的变种,即阻塞多读调用。
通过这一系统调用可以对多个设备指定所需的读取,而且只要一个完成就可返回。