linux操作系统 第08章 设备管理

                                                                                         第8章  设 备 管 理


1  设备管理概述
1.1  设备的分类
  计算机系统中除CPU和内存之外的所有设备都称为外部设备(I/O设备)。计算机系统中的设备种类繁多,虽然它们的物理形态、技术特性和操作方式等各不相同,但都可以看作是完成某种输入/输出操作的功能部件。对设备进行分类的标准有多种。可以按照不同的指标对设备进行分类。

  1. 输入设备与输出设备
  按数据传输方向的不同,I/O设备分为输入设备输出设备输入/输出设备3类。输入设备用于从外界采集或产生数据,传送给系统。如键盘、鼠标等都是输入设备。输出设备是从系统获得数据,以某种形式向外界表现或传递的设备。如显示器、打印机等都是输出设备。输入/输出设备则是兼具输入与输出数据功能的设备。如磁盘、网络、串口设备等都是输入/输出设备。

  2. 系统设备与外部设备
  系统设备是由系统内核管理和使用的设备,如系统时钟、系统扬声器、总线接口等。系统设备之外的设备都属于外部设备。两者区别在于系统设备的驱动由内核本身完成,而外部设备的驱动由专门的驱动程序实现,以内核模块的方式附加到内核中。因此,外部设备可以被安装和卸载,而系统设备则不能。本章所介绍的内容只针对外部设备。

  3. 字符设备与块设备
  按数据传输单位的不同,设备分为字符设备和块设备。字符设备:以字节为单位组织和传送数据的设备,如终端设备(显示器、键盘、鼠标等)、打印机、串口设备等。
块设备:以数据块为单位组织和传送数据的设备,如磁盘、光盘、闪存等。
  

  4. 独占设备与共享设备
  按设备的使用方式,设备分为独占设备和共享设备。
  
独占设备:在某一时间段内只能被一个进程所使用的设备。打印机、终端设备等都是独占设备。当一个进程占用打印机输出时,其他要打印的进程只能等待。
  
共享设备:允许多个进程同时使用的设备。磁盘等存储设备都是共享设备,它们允许多个进程同时访问文件,存取文件的数据。

1.2  设备管理的功能
  设备是系统中的重要资源,无论是用户程序还是内核本身都要使用到设备。设备管理的目标有两个:一是从资源的角度出发,要尽可能地提高设备的使用效率,提高I/O系统的性能;二是从用户的角度出发,设备管理系统要屏蔽各种设备的物理特性,为用户提供一个统一的、方便的I/O操作界面。
  具体来说,设备管理主要完成以下功能:
  
(1) 设备的分配:根据设备的特点对设备进行合理的分配和调度。

  (2) 设备的驱动:根据进程的I/O请求,启动设备进行操作,控制数据的传输。
  
(3) 设备的中断处理:对设备产生的中断进行处理。
  
(4) 虚拟设备:用共享设备模拟独占设备,实现虚拟设备。

1.3  设备与系统的接口
  计算机的I/O设备通常由物理设备和电子部件两部分组成。物理设备是以某种物理方式(机械、电磁、光电、压电等)运作,实际执行数据I/O操作的物理装置;电子部件是以数字方式操作的硬件,用于与计算机接口,控制物理设备的I/O操作。
  一个物理设备是无法直接与
CPU相连接的,这是因为两者之间存在着以下差异:
  
(1) 控制方式不同:CPU产生的是数字化命令,而设备需要某种物理信号来控制。

  (2) 传输方式不同CPU以字节为单位传输数据,而设备可能是以位为单位传输的。
  
(3) 速度不匹配:设备的工作速度要比CPU慢许多。
  
(4) 时序不一致:设备有自己的定时控制电路,难以与CPU的时钟取得一致。
  
(5) 信息形式不同CPU表达信息的形式是数字的,设备则可能是模拟的。
  基于以上分析,
CPU与设备的连接必须解决译码解码、数据装配、速度匹配、时序同步以及信息格式转换等诸多问题。这需要借助一个介于CPU与物理设备之间的硬件接口来实现,这就是I/O设备的电子部件要完成的功能。

  1. 设备控制器
  在许多情况下,I/O设备的电子部件与物理设备是分离的。电子部件称为设备控制器,物理设备就简称为设备。例如:显卡是显示控制器,显示器是由显卡控制的设备;声卡是音频控制器,音箱或耳机是音频设备。
  控制器通过总线插槽
(ISAPCI)接入系统总线。一个控制器可以带多个同类型的设备。设备控制器是CPU与物理设备之间的接口,它接受从CPU发来的命令,自行控制I/O设备工作。
  设备控制器的复杂性因设备而异,相差很大。控制器的典型结构如图7‑1所示。

图7‑1  设备控制器的典型结构

  设备控制器通常由以下部分组成:
 
 1)  I/O端口
  I/O端口由一组寄存器组成,它们是设备与CPU的接口。根据设备复杂程度的不同,端口寄存器可多可少,通常会包括数据寄存器、控制寄存器和状态寄存器。控制寄存器用来存放从CPU接收到的命令和参数,用以启动设备或者改变设备的工作模式;数据寄存器存放要传输的数据;状态寄存器记录设备的当前状态,用来指示当前命令是否执行完毕以及是否有任何错误发生。
 

         每个I/O端口寄存器都具有一个可被CPU访问的独立的地址。CPU通过专门的I/O指令读/写设备的I/O端口,实现对设备的控制和数据交换。在执行I/O指令时,CPU使用地址总线选择所请求的I/O端口,使用数据总线在CPU寄存器和端口之间传送数据。

  2) 缓冲区
  在块设备以及数据流量大的设备(音频、视频等设备)的控制器中通常还配有缓冲区,用于存放批量传输的数据。缓冲区通常由寄存器或高速存储芯片组成,缓存区的地址被映射为内存地址,可以被CPU直接访问,它们也可以通过总线直接与系统内存交换数据。

  3) 设备控制逻辑
  设备控制逻辑是I/O端口与设备之间的翻译器,它的主要功能包括:
  
(1) 命令译码:设备控制逻辑负责对控制寄存器中的I/O命令进行译码,确定具体的设备,产生对设备的一系列控制信号,控制设备的操作。例如,磁盘控制器接收到I/O命令后,先要根据实际磁盘的几何结构对I/O请求进行优化,确定访问位置及顺序;然后进行译码,产生驱动磁头定位和数据读/写的磁盘操作信号,发送给磁盘驱动器。
  
(2) 状态解释:当设备执行完一个操作后,设备控制逻辑对从设备接收到的状态信号进行解释和编码,存入状态寄存器。

  (3) 信息格式转换:控制逻辑需要完成I/O端口与设备之间的数据转换,主要是串行和并行的转换,以及数/模或模/数转换等。
  
(4) 传输控制:控制逻辑负责控制I/O端口或缓冲区与设备之间的数据传输,以及I/O端口或缓冲区与CPU之间的数据传输。为此,控制逻辑需要具有中断请求的功能,块传输时还需要有缓冲区读/写控制以及DMA请求的功能。

  4) 中断与DMA控制
  大部分的设备都工作在中断方式下,它们具有中断控制的逻辑,可以向中断控制器发送中断请求信号并接收中断控制器发回的中断应答信号。启用了DMA方式的控制器还具有DMA控制逻辑,可以向DMA控制器发送DMA请求和接收DMA应答。
  
5) 设备接口
  设备接口是控制器与设备之间的接口。一个控制器可以连接多台设备,每个接口连接一台设备。设备接口主要负责针对具体设备的信号发送、数据和状态采集等操作。

  2.  I/O接口
  出于通用性设计的考虑,计算机硬件结构都提供了一些标准的设备接口,这些接口遵照统一的标准来设计,不同的设备只要遵从同一标准即可通过该接口与系统连接。根据所接驳的设备种类的不同,可以将I/O接口分为两类:一类是可连接各种类型的设备的通用接口,如串口、并口、USB接口等都属于通用I/O接口;另一类是为连接某类设备而设置的专用接口,如IDESCSI接口都是块存储设备的专用接口。一个I/O接口可以带多个同类型的设备。例如一个IDE接口可以带两个IDE磁盘驱动器。

  通过I/O接口连接设备的方式可以看做是将设备控制器的功能分散实现了:I/O接口实现与CPU直接连接部分的功能,包括I/O端口、缓冲区、中断及DMA控制等。而与设备直接相关的控制逻辑则由设备自行实现。例如,IDE硬盘连接在IDE接口上,磁盘设备通过这个接口与CPU通信,而与磁盘直接相关的控制器部分则与物理的磁盘驱动器集合在一起,这从IDE (Integrated Device Electronics,集成设备电路)的名称可以看出。

  标准的I/O接口为设备的开发和使用提供了方便,设备部分只需实现必要的设备控制功能即可。这种自己带有一定控制功能的设备称为“智能”设备。例如:IDE的磁盘驱动器就是这样的设备,其他许多串口设备、USB设备等都是具有某种程度智能的设备。从这个观点出发,I/O接口可以看做是简化了的设备控制器,而设备则可看做是“智能化”了的设备。习惯上我们经常称一些专用的I/O接口为控制器,如IDE控制器、SCSI控制器等,而称那些通用的I/O接口就是某某接口了。

  3. 设备与系统的连接
  归纳起来,设备与系统的连接方式主要有两种:一种是集成的设备控制器+“(dumb)”设备,如内置声卡+音箱;另一种是I/O接口+“智能(intelligent)”设备,如USB接口+USB音箱(USB接口+外置声卡+音箱)。为叙述上的方便,我们把这些方式都看做是一种,就是设备控制器+设备

  4.  I/O设备的资源
  I/O设备与系统通信必须首先获得一些系统资源,主要是I/O端口的地址和中断申请号等。控制器是资源的占有者,系统以控制器为对象来分配资源。
  
I/O设备的资源有如下几种:
  
(1)  I/O端口地址:控制器中的每个I/O端口寄存器都有一个唯一的地址,一个控制器所拥有的I/O端口地址的总和称为该设备的I/O范围。如COM1I/O范围为0x03f80x03ff
  
(2) 中断申请号IRQ:设备申请中断使用的中断线号码。
  
(3) 缓冲区地址:控制器中的缓冲区所映射的内存地址范围。

  (4)  DMA通道号:设备申请DMA使用的DMA通道号码。
  在安装设备时,由系统为控制器分配这些资源,并保证各个设备的资源彼此不相冲突。只有正确地配置了设备的资源,才能保证设备能够正常地工作。

1.4  I/O系统的硬件结构
  对于不同规模的计算机系统,I/O系统的结构也有较大的差异。大致可以分为主机I/O系统微机I/O系统。主机系统的设备较多,对传输速度的要求也高,因而采用具有通道的I/O系统结构。微机的I/O系统结构则比较简单,通常采用总线结构,即CPU、内存和I/O设备都连接到总线上,如图7‑2所示。

图7‑2  微型机I/O体系结构

  总线体系结构的特点是以总线为纽带。系统板上的部件都通过总线相连,所有的信号都要通过总线进行传输。系统总线分为3个逻辑功能部分:地址总线、数据总线和控制总线。地址总线指定数据传送的地址;数据总线用于传送数据;控制总线包含一些信号线,用来控制时序和系统中的其他控制信号,如中断请求、DMA请求信号等。
  总线由CPU控制,
CPU可以通过总线访问内存和设备,以及控制在内存和设备之间传输数据。总线采用独占使用方式,任何设备若需要直接和内存交换数据,先要申请总线使用权,获得使用权后独占总线进行通信。

  在总线结构系统中,数据的交换路线主要有以下两种:
  (1)  
CPU与慢速的字符设备交换数据时,由CPU控制设备与内存之间的数据交换。输入时,CPU从控制器中将数据读到CPU的内部寄存器中,再写到内存单元中;输出时则相反,将内存数据读到CPU的寄存器中,再写到控制器的数据寄存器中。
  
(2)  CPU与高速的块设备交换数据时,以DMA方式进行。DMA控制器先申请总线使用权,然后控制设备直接与内存传输数据。关于DMA技术的介绍见2.3小节。

1.5  I/O系统的软件结构
  I/O软件是控制设备与内存、CPU进行数据交换的所有软件的统称。其主要的任务是充分发挥各种设备的作用,屏蔽各种设备的特殊性,在保证系统具有较高的整体性能的同时,尽可能向用户提供一个方便、规范的设备使用界面。
  I/O软件大多采用分层结构,底层软件用来屏蔽硬件的细节,高层软件则主要为用户提供一个规范的使用接口。图7‑3所示为I/O系统的软件结构。

图7‑3  I/O系统的软件结构

  分层结构的底层是设备相关部分,称为设备驱动程序。它们直接和相应的设备打交道,负责设备的具体驱动和控制。上层通常是和设备无关的,这个部分接受来自用户层的访问请求,并把这些访问请求传给具体的设备驱动程序,再将驱动程序的执行结果进行转换,传给用户。各个部分的功能大致如下:
  (1)
设备命名与保护:为方便用户指定设备,I/O系统应按某种规则对每个设备加以命名。用户用设备名来访问设备,由I/O系统完成从设备名到设备的映射。系统还应对每个设备指定访问权限,防止设备被非法使用。

  (2) 缓冲区管理:块设备(以及某些字符设备)的数据传输采用缓冲方式。在传输数据前,系统需要在内存中为设备分配缓冲区;传输结束后,系统还要管理缓冲区,为后续的I/O操作提供缓存功能。
  
(3) 设备分配:在多任务系统中,进程可能会竞争设备,因此系统必须有一个分配程序来分配和调度设备资源。当进程向系统提出I/O请求时,设备分配程序便按一定的策略将设备分配给进程使用。

  (4) 设备驱动与中断处理:驱动程序是操作硬件控制器的软件。驱动程序利用上层传来的指令,操纵设备控制器读/写数据,设备控制器则控制设备进行具体的数据I/O操作。当设备完成I/O操作后,向CPU发出中断请求,CPU转入中断处理程序进行处理。

     设备管理的相关技术
  现代设备管理普遍采用了一些关键技术,主要是中断技术、缓冲技术、通道技术、DMA技术等。这些技术的目标都是为了提高数据传输速率和系统的并发程度,优化系统的整体I/O性能。

2.1  中断技术
  1. 中断的概念

  在计算机运行期间,当系统内部或外部发生了某个异步事件需要CPU处理时,CPU将暂时中止当前正在执行的程序,而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处,继续执行或者调度新的进程执行,这个过程就称为“中断”(interrupt)。异步事件是指与系统运行没有时序关系的、不可预期的事件,如用户按下键盘按键、磁盘传输数据完成、系统硬件出现故障等都是异步产生的事件。

  在中断技术出现之前,CPU启动设备进行I/O操作后,要不断地探察设备控制器的“忙/闲”状态位,直到设备完成操作。在这种I/O控制方式下,CPU与设备是串行工作的,这对CPU来说是极大的浪费。中断技术实现了由设备向CPU报告的手段,这样,CPU启动设备操作后可以继续进行其他计算,不必再轮询设备了。因此,中断使得CPU可以与设备并行工作,极大地提高了系统的运行效率。

  中断技术最早应用在I/O传输过程中,它使外部设备和CPU的并行工作成为可能。而后中断技术扩大到设备之外的其他事件。现在,凡是需要CPU干涉或处理的异步事件都采用中断的手段进行处理。可以看出,中断对于操作系统的意义重大,它是系统一切并发活动的基础,因而是操作系统最基本的技术。

  2. 中断源与中断分类
  引起中断发生的事件称为中断源。通常中断源是由硬件产生的信号,目的是通知CPU某个需要处理的事件。例如,当敲打键盘时,键盘控制器就会产生一个键盘中断源信号。
  在计算机系统中有很多种类的中断源。其中,由设备数据传输过程中发生的中断属于
I/O中断,是中断源中的一大类。其他中断源有周期性的时钟中断、电源掉电产生的中断等。此外,一些来自CPU内部的事件或程序执行中的异常事件(CPU故障、除数为0、内存溢出、执行了陷入指令等)也会被作为中断对待和处理。这类由内部故障或程序故障引起的中断事件称为“异常”(exception)。

  3. 中断请求
  中断源需要通过中断线送到中断控制器的输入端,这称为中断请求。中断控制器是一个硬件装置,它负责捕获中断请求,并以一定的方式向CPU提交中断。由于同时可能会有多个中断信号产生,它们需要共用有限的中断线。因此,当设备要使用中断线时就要先进行中断请求(IRQ),以获得中断线的使用权。

  4. 中断响应
  对中断请求的整个处理过程是由硬件和软件相结合的一整套中断机构实施的。中断响应由硬件实施,中断处理主要由软件实施。
  CPU在收到来自中断控制器的中断信号后,暂停执行当前的进程,转入相应的中断处理程序进行处理,这个反应的过程称为中断响应。通常CPU在执行完一条指令后,会检查有无中断请求。如有,则会立即作出响应。
  一般说来,中断响应过程顺序执行下述动作:
  (1) 中止当前进程的执行;

  (2) 对被响应的中断进行应答;
  
(3) 保存当前进程的断点信息(主要是程序状态字PSW和程序计数器PC)
  
(4) 转到中断处理程序入口。
  所有中断处理程序的入口地址都保存在一个
中断向量表中。CPU在响应中断时,根据中断源检索中断向量表,得到的中断向量中包含相应中断处理程序的入口地址和程序状态字。将中断向量加载到CPU中,在下一个指令周期CPU就会转去执行相应的中断处理程序了。

  并不是所有中断请求都会得到及时的响应。在很多情况下,比如系统正在执行内核的进程调度或者内存调度操作,为了保证操作的原子性,这时不允许CPU响应中断。在这种情况下,CPU通过设置中断机构,使其不产生中断请求,这个过程称为关中断。当CPU完成必要的操作之后必须对硬件重新设置才能够接收中断,这个过程称为开中断。

  5. 中断处理
  中断处理主要由软件实施。响应中断后,CPU转去执行相应的中断处理程序。每个中断都对应一个特定的中断处理程序,因而系统中会有许多中断处理程序,如时钟中断处理程序、键盘中断处理程序等。在设备的驱动程序中包含了对该设备所有中断的处理程序。
  中断处理程序的执行过程大致分为如下几个阶段:

  1) 保存现场
  现场指的是在程序运行时CPU中的各个寄存器、计数器的状态。通常,中断响应时硬件处理的时间很短,只保存了程序状态字等现场信息。在随后的中断处理过程中,其他一些寄存器的内容可能会被改变。因此,在进入中断处理程序时,首先要将那些在中断处理程序中要用到的寄存器的内容保存在堆栈中,以便在处理完成后可以恢复它们。

  2) 处理中断
  中断的处理方式因中断的不同而异。对于I/O中断来说,通常是从设备控制器读取设备状态,判别此次中断是正常完成中断还是异常结束中断。若是完成中断,则进行结束处理,需要的话再向控制器发送新的命令,启动下一轮数据传送。若是异常结束中断,则根据异常的原因做相应的处理,比如重试或报告错误。
 
 3) 恢复现场
  恢复现场是将保护现场时保存的数据恢复到CPU的寄存器中。

  4) 中断返回
  中断处理程序完成处理后,执行一个特定的中断返回指令。该指令将恢复程序的断点信息(PSW和PC),使原来被中断的程序恢复执行。有时,中断处理程序也可能需要唤醒某些睡眠进程。如果设置了重调度标志,则在中断返回时会引起系统重新进行进程调度,选择一个新的进程运行。

2.2  缓冲与缓存技术
  中断技术的引入,使得系统中各I/O设备之间以及I/O设备和CPU之间可以并行工作。但I/O设备与CPU的处理速度存在着巨大的差异,这导致进程在需要传输大量数据时不得不经常等待。因此,I/O设备与CPU的速度不匹配的问题制约了系统性能的进一步提高。解决此问题的有效方法是缓冲技术

  1. 缓冲技术
  缓冲(buffer)技术就是为了解决设备和CPU之间处理速度不匹配的问题而引入的。CPU的数据传输速度可以达到纳秒级,而对于像磁盘这样的机电存储设备,其数据传输速度是微秒级的。两者直接交换数据就如同将一个大口径的水管与一个小口径的水管连接起来,必然会产生性能上的瓶颈问题。结果就是,进程运行中在高速地产生或处理数据,却不得不时时等待低速的设备慢慢地输出或输入这些数据。

  产生这一问题的根源在于CPU处理数据的速度与I/O设备处理数据的速度不相匹配。实际生活中,凡是存在输出与输入速度不匹配的地方都可以采用缓冲技术来解决。比如,为了缓解降水与灌溉用水的速度不匹配问题,可以用修建水库的方法,这就是缓冲的思想。对于I/O操作来说,缓冲的思想就是在高速存储区(内存或高速缓存)内设置缓冲区。进程要进行输出时,将数据高速地倾泻到缓冲区中,然后继续执行后续操作。输出设备则按自己的速度从缓冲区中取出数据并完成输出操作。对于数据输入操作则正好相反。设备将输入数据写入缓冲区中,数据准备好后用中断通知CPU,然后进程直接从缓冲区高速地获取输入数据。这样就缓解了进程的等待现象,从而提高CPU与外设之间的并行程度。

  2. 缓存技术
  与缓冲技术有着细微差别的另一个技术是
缓存(cache)技术缓存区(cache memory)是为了临时存放与设备交换的数据而设置的数据暂存区,通常位于内存或设备控制器的内存芯片中。在数据传输过程中,缓存区起到I/O缓冲的作用,同时对通过缓存区的数据保留备份。当下一次访问数据时首先在缓存区中查找,如果命中则不需要启动外部设备就可以立即从缓存中得到数据,其读/写速度是内存级的;如果查找没有命中,则启动设备进行数据I/O操作。这样,经过一段时间的积累,经常访问的数据基本都在缓存区中,系统启动设备的次数就会大大降低,系统的I/O效率因此而显著地提高,同时还可延长设备的使用寿命。

  操作系统中广泛地应用了缓存技术,如文件系统中的i节点缓存、目录项缓存等。内存管理中的快表和slab也是一种缓存。此外,应用软件中常用缓存技术来提高性能,如Web服务器将经常被访问的网页保存在缓存中,以提高网络访问速度,减少网络流量。

  3. 缓冲与缓存的差异
  缓冲与缓存的基本原理和作用是相似的,如果不加区分的话,都可以称之为缓冲。但两者之间确实存在细微的差异:
缓冲的作用在于协调速度不匹配的I/O传输过程,而缓存的作用在于减少对设备的实际访问次数。这个差异导致了两者的管理方法有所不同。
  一般来说,
缓冲区的生命期较短,当进程开始数据传输时建立,一旦数据传输完毕,将立即释放缓冲区,它只起暂存数据的作用。而缓存区的生命期较长,缓存的数据可以长时间地保存在缓存区中,服务于各种应用目的。如文件系统中的i节点缓存、目录项缓存等在整个系统运行期间都存在于内存中,由文件系统管理和使用。

  另外,缓冲区的管理相对简单,系统只需提供简单的分配算法以及同步机制即可。而缓存区的管理则需要利用更复杂的算法,以提高访问的命中率,最大限度地发挥缓存的作用。例如,磁盘的缓存算法要确定哪些数据应存放在缓存中,哪些数据应从缓存中撤出等。
  在应用上,进程间的通信多使用缓冲技术,而设备的I/O往往使用缓冲兼缓存技术。

  4. 缓冲的实现方式
  根据缓冲区所在的位置,可以分为硬缓冲和软缓冲两种。硬缓冲就是设备自带的缓冲区,位于设备控制器或设备上,软缓冲是在内存中开辟的缓冲区。
  
1) 软缓冲的实现方式
  软缓冲是在内存中设置缓冲区,用于暂存数据供进程快速地获取或输出。根据设置的缓冲区的个数,缓冲区分为以下几种:
  
(1) 单缓冲:只设置一个缓冲区。由于缓冲区属于临界资源,读/写此缓冲区的进程或设备必须串行访问。

  (2) 双缓冲:设置两个缓冲区,当一个进程写一个缓冲区时,另一个进程可以读另一个缓冲区,这样就在一定程度上实现了读/写操作的并行性。
  
(3) 环形缓冲:将多个缓冲区连接成一个环形,输入进程沿着环路顺序地写各个缓冲区,输出进程随后顺序地读各个缓冲区。只要后者没有追上前者,它们就可以并行地工作。环形缓冲提高了读/写的并行化程度,缓冲的效果更好。
  
(4) 缓冲池:以上缓冲区都是为某个I/O进程设置的,属于专用缓冲区,利用率不高。缓冲池是一组公用缓冲区,由专门的管理程序统一管理,供多个I/O进程共享。进程需要时就申请,使用完毕后再释放。这种管理方法提高了缓冲区的利用率。

  2) 硬缓冲的实现方式
  硬缓冲就是在设备上设置缓存器,在设备内部存储和I/O接口之间起到一个缓冲和缓存的作用。以磁盘缓存为例,磁盘上带有一个存取速度极快的缓存芯片,用于暂存读/写的数据块。在读取磁盘时,磁盘控制器会控制磁头把正在读取的数据块的下一个或者几个块中的数据读到缓存中。下次执行读操作时先在缓存中查找,如果命中则可立即送出数据,而不必启动磁盘操作。由于磁盘上数据存储是比较连续的,所以下一次的读取命中率会较高。写入数据时,磁盘并不会马上将数据写入到盘片上,而是先暂存在缓存里,然后发送给系统一个操作完成中断。而后,磁盘在空闲时再将缓存中的数据写入到盘片上。

  从磁盘缓存的例子中可以看出,使用缓存可以减少访问设备的中断次数和延迟,提高设备的使用寿命。另外,缓存的大小直接关系到设备的传输速度,大的缓存能够大幅度地提高设备的整体性能。现今主流磁盘所采用的缓存容量一般是8~16 MB,在服务器中的磁盘缓存容量可以达到16~64 MB。

2.3  DMA技术
  用中断方式控制I/O传送时,每传送一个字节或字就要向CPU发一次中断请求,传输1 KB数据需要发一千多次中断请求,这对于块设备来说效率太低。为了减少CPUI/O传输过程的干预,在PC机系统中引入了DMA方式,用来控制块设备的批量数据传送。
  
DMA直接存储器访问(Direct Memory Access),其思想是用一个特殊的设备控制器来控制块设备,使其可以直接与主存交换数据。这个控制器就称为DMA控制器

  在以总线为中心的体系结构中,任何数据交换都要通过总线进行。总线控制权在CPU,也就是说,所有的数据交换都需要CPU参与完成,外设无权使用总线直接访问内存。DMA控制器的特殊之处在于它能从CPU那里暂时地获得总线控制权,在没有CPU的参与下控制外设与内存直接传送数据。直接的意思就是指数据传送不必经CPU的寄存器为中介,可直接从设备写入内存或从内存送入设备。在整个传输期间,设备不产生任何中断,仅在全部数据传输完成后才向CPU发出中断。

  在启用了DMA控制的设备中,通常在控制器中设置了数据缓存区。设备先把数据准备好,放在缓存中,然后只需一次中断就可以完成数据传输,使系统效率得到明显的改善。
  一个完整的DMA传输过程需要经过下面的4个步骤。

  1.  DMA请求
  CPU通过I/O指令对DMA控制器初始化,向DMA控制器发送要启动的设备号、数据传输的内存起始地址、要交换的数据字节数等参数。随后,CPU向设备控制器发出操作命令,设备控制器准备好数据后,向DMA控制器提出请求。
  
2.  DMA响应
  DMA控制器对DMA请求予以判别,然后向CPU发出总线使用权的请求。CPU在本机器周期执行结束后响应该请求,与系统总线脱离。而后,DMA控制器接管数据总线与地址总线的控制,开始控制DMA传输。

  3.  DMA传输
  DMA控制器获得总线控制权后,对设备控制器发出读/写命令,控制设备直接与内存进行数据传输。在传输过程中,DMA控制器对传送的字节进行计数。当传输的数据块达到预定的字节数时传输完毕。

  4.  DMA结束
  完成规定的批量数据传送后,DMA控制器即释放总线控制权,向设备控制器发出结束信号,并向CPU提出DMA中断请求。CPU响应中断后转到中断处理程序中处理DMA的结果,处理内容包括校验送入内存的数据是否正确,测试在传送过程中是否发生了错误,决定是否继续传送下去等。中断处理完成后,CPU返回原来的进程继续执行。
  可以看出,
DMA方式有如下特点:数据传输的基本单位是数据块;所传输的数据是从设备直接送入内存的,或者相反。整块数据的传送是在控制器的控制下完成的,仅在传输的开始和结束时才需要中断CPU。因此,DMA方式成百倍地减少了CPU对I/O控制的干预,大大提高了CPU与设备的并行化程度。

  实现DMA的方式主要有周期挪用方式CPU停机方式,目前后者更为常用。无论哪种方式,在DMA传输过程中都会占用CPU的工作周期,CPU的利用率自然会有所降低。因此,DMA控制器能带的设备数量有限,只适用于PC机等低端机型。

        3    I/O控制方式
  I/O控制就是控制数据在I/O设备与CPU、内存之间的传输,这是设备管理的一个主要功能。随着计算机技术的发展,I/O控制方式也在不断地发展。从最早的程序I/O方式,发展到中断驱动方式、DMA控制方式和通道方式,数据传输速率不断提高。而贯穿整个发展过程的一条宗旨就是尽量减少CPUI/O控制的干预,把CPU从繁杂的I/O控制事务中解脱出来,提高CPU与外设的并行化程度。

3.1  程序I/O方式
  在设备控制器的状态寄存器中,有一个用于表示设备工作状态的“忙/闲”(busy)标志位。进程通过执行I/O测试指令可以检测这个标志位,获得设备的当前工作状态。程序I/O方式就是由执行I/O的程序直接访问这个标志位来控制设备的I/O操作的方式。以输入为例,程序通过I/O命令启动设备,设备开始准备数据,并设标志位为“忙”(busy=1)。在数据准备过程中,程序循环地检测“忙/闲”位,直到设备准备好了数据,并将“忙/闲”标志位置为“闲”(busy=0)。进程取走数据,继续下面的执行。图7‑4描述了程序控制I/O方式的操作时序。

图7‑4  程序控制I/O方式的操作时序

  在整个传输过程中,进程一直占用着CPU,而CPU所做的大量工作是不断地查询设备的状态,所以这种传输方式也称为轮询(polling)方式。由于外备的速度比CPU要低很多,使CPU的大量时间浪费在轮询上,因此,在这种方式下CPU与外设实际上是串行工作的,CPU的利用率非常低。
  程序I/O方式是早期计算机系统采用的/I/O方式。它不需要额外的硬件支持,甚至可以不需要驱动程序。目前多用在一些单片机等简单系统中。

3.2  中断I/O方式
  中断I/O方式的过程是:当进程需要数据传输时,CPU为其启动设备进行I/O操作。此后CPU不是被动地测试等待,而是将原进程挂起,继续执行其他进程。设备控制器按照I/O命令的要求控制设备进行数据传输,当设备完成I/O操作后,采用中断方式向CPU报告。CPU响应中断后,暂时停止当前进程的执行,转去进行中断处理,然后唤醒等待数据传输的进程,转入就绪状态。中断处理完成后,CPU转到被中断的进程或新调度的进程继续执行。图7‑5描述了中断驱动的I/O方式的操作时序。

图7‑5  中断I/O方式的操作时序

  中断I/O方式的优点是显而易见的。在中断方式下,CPU与I/O设备是并行执行的,这样可以使CPU和I/O设备都处于忙碌状态,从而提高了整个系统资源的利用率和吞吐量。但中断方式需要硬件和软件上的支持。系统需要设置一个中断机构来响应中断,还需要一组中断处理程序来处理中断事件。响应中断时的保留和恢复现场以及处理中断时执行的中断处理程序都要耗费CPU的时间。因此,在进行大量数据交换时,频繁发生的中断会使系统的性能降低。

3.3  DMA方式
  DMA方式的传输过程是:当进程需要数据传输时,CPUDMA控制器发出启动命令,同时把设备号、内存地址和数据量等参数通知DMA控制器。此时原进程转入等待状态,CPU继续执行其他进程。DMA控制器控制设备不断地与内存传输数据,直到所有数据传输全部完成,然后通过中断通知CPU进行相应的中断处理。处理完成后,唤醒等待数据的进程。图7‑6描述了DMA方式的I/O操作时序。

图7‑6  DMA方式的I/O操作时序

  在DMA方式中,整个数据块的传输过程不需要CPU的干预,较之中断方式又大大降低了CPU的负担,进一步提高了CPUI/O设备的并行操作程度。
  DMA方式的缺点是会降低进程的运行效率,尤其是DMA设备较多时,需要占用较多的CPU工作周期,对其他进程的影响会很大。

3.4  通道方式
  对于追求高效的中大型机器多采用具有独立处理器的通道来实现I/O传输控制。通道(channel)是一个专门用于控制I/O操作的处理机,它执行通道程序,控制外设与主存之间交换数据。通道的工作过程是:CPU生成通道程序,启动通道执行,然后继续执行进程。这段时间中,通道与CPU是完全并行工作的,CPU执行进程,通道执行通道程序,控制设备与内存传输一批数据。传输结束后,通道产生通道中断向CPU报告,CPU处理完通道中断后就可以直接使用内存的数据了。

  由于通道是可独立运行的硬件,所以它的运行不会影响到CPU的执行效率。通道承担了所有的I/O控制工作,使得CPU可以完全摆脱对I/O操作的干涉,因而采用通道结构的系统具有非常高的I/O性能。

     设 备 的 分 配
  由于设备资源的有限性,所有的设备都由I/O管理系统进行统一地管理和调度。进程需要进行I/O操作时,必须向系统提出申请,由系统为它分配设备。如果进程得不到所申请的设备资源,它将被放入等待队列中等待,直到所需的设备可用。

4.1  设备分配策略
  设备分配是由I/O系统中的设备分配程序完成的。每当进程提出I/O请求时,设备分配程序便按照一定的策略把所需的设备分配给进程使用。设备分配的原则是要尽可能地让设备忙碌,充分发挥设备的使用效率。

  1. 分配方式
  设备的分配方式有静态分配动态分配两种,静态分配是在进程开始运行前就一次性地为它分配所有需要的设备,进程在运行期间一直保持这些设备,直到运行结束后才释放。静态分配的算法简单,但设备的利用率低。
  动态分配就是进程在运行过程中根据需要提出对设备的请求,系统按分配算法为它分配设备,使用结束后立即释放。动态分配有利于提高设备的利用率,因而是现代系统普遍采用的分配方式。不过动态分配的算法要设计适当,否则容易造成进程的死锁。

  2. 分配策略
  设备分配时主要应考虑的因素是与分配有关的设备属性,即设备是独占设备还是共享设备。对于独占设备,应采用独占分配策略,也就是将一个设备分配给某进程后便一直由它独占,直至该进程完成或释放该设备,然后系统才能把这个设备分配给其他进程。而对于共享设备,系统可以将它同时分配给多个进程使用,同时系统还要合理地调度这些进程对设备的访问次序。
  由于独占设备只能采用独占分配,因而设备的利用率低。解决这个问题的一个策略是采用虚拟分配,即为进程分配一个虚拟的设备,具体的实现技术见4.2小节。

  3. 分配算法
  当有多个进程同时请求设备时,系统应采用某种策略决定将设备分配给哪个进程使用。主要的分配策略有先来先服务和优先级两种。
  
先来先服务算法根据进程对某设备提出请求的先后次序,将这些进程排成一个设备请求队列,设备分配程序总是把设备首先分配给队首的进程。先来先服务的算法简单、公平,但无法满足某些紧迫进程对I/O响应时间的要求。
  
优先级算法的策略是对高优先权进程的I/O请求也赋予高优先权,这有助于这种进程尽快完成。在利用该算法形成设备队列时,将优先级高的进程排在设备请求队列的前面,而对于同优先级的I/O请求,则按先来先服务的原则排队。

  4. 设备分配的相关数据结构
  为了实施对设备的管理和分配算法,设备分配程序需要用到一些数据结构来记录设备的相关信息。主要的数据结构有设备控制表(DCT)控制器控制表(COCT)系统设备表(SDT)等。每个设备都对应有一个设备控制表,用于记录该设备的信息,包括设备标识、使用状态和等待进程队列等。每个设备控制器对应一个控制器控制表,用于记录该控制器的信息,包括控制器的标识和使用状态等。整个系统有一个系统设备表,它记录已连接到系统中的所有设备的情况,每类设备占一个表项,内容包括该类设备的标识、数量、等待队列以及设备控制表的位置等

4.2  虚拟设备技术
  独占设备在一个期间内只能被一个进程使用,由于设备的速度很慢,造成其他要使用同一设备的进程不得不长时间地等待。例如,假设有多个进程要使用打印机,每个进程的打印时间以分钟计。当第一个获得打印机的进程正在打印时,排在后面的所有进程都必须长时间地等待。这样就严重影响了进程的执行速度,极端情况下还会引起死锁。因此,独占设备是I/O系统性能的“瓶颈”。

  要解决独占设备分配所带来的问题,最根本的策略就是用某种方法将其转化为一个共享设备,而实现这种转换的有效方法就是假脱机(SPOOLing)技术SPOOLing的思想是在高速共享设备上模拟出多台低速独占设备,从而提高系统效率。这种模拟出来的设备并不实际存在,所以称为虚拟设备。
  
SPOOLing系统的实现方案是在外存储器中开辟一些缓冲区,称为“I/O井”。用户进程需要与设备交换数据时,只对I/O井高速读/写数据,由SPOOLing系统控制在适当的时候将I/O井中的数据传输给实际设备。对用户进程来说,I/O井就是一台高速的虚拟设备。

  图7‑7描述SPOOLing系统的工作原理。系统在外存开辟了一个打印机输出井和一个磁带机输入井。对用户进程来说,这就是一台虚拟打印机和一台虚拟磁带机。当进程需要从磁带机输入数据时,SPOOLing系统启动磁带机,将数据读入磁带机输入井中,随后进程直接从输入井提取数据,不需再等待。当进程需要打印输出时,它们将数据高速地送入打印机输出井,然后继续运行。在输出井等待打印的数据形成打印队列,由SPOOLing系统控制在适当的时候完成实际的打印工作。
  虚拟设备除了可以减少进程对设备的等待时间外,还可以解决多个进程对独占设备的竞争问题。例如,在设置了虚拟打印机的系统中,每个进程都可以随时执行打印输出操作,好像系统的打印机是自己独占的。也就是说,使用虚拟设备永远不会引起进程死锁。

图7‑7  SPOOLing系统工作原理示意图

      设 备 的 驱 动
  设备的驱动是I/O系统最底层的功能,由设备驱动程序完成。
5.1  设备驱动程序
  设备驱动程序(device driver)是直接管理和操纵设备控制器的软件。它是针对具体的设备控制器设计的,每个设备控制器都由一个特定的设备驱动程序来控制。设备驱动程序是内核的一部分,它们运行在核心态,可以访问控制器的I/O端口,驱动各自的设备。
  
设备驱动程序是设备管理的主要软件之一。从图7‑3中可以看出,设备驱动程序位于I/O软件系统的底部,它们使用一致的接口与I/O系统相连接,将设备的特殊性在这个层次中隐藏起来。设备驱动程序接受上层I/O软件的I/O请求,将其转化为设备控制器的命令代码,操纵设备控制器完成数据传输的全过程。图7‑8所示是设备驱动程序与控制器的关系。

图7‑8  设备驱动程序与控制器的作用关系

  设备驱动程序与设备控制器交互的大致过程是:驱动程序将控制命令发到控制器的命令寄存器中,控制器启动设备进行I/O操作。当数据准备好后,驱动程序负责与控制器交互,完成数据传输工作。控制器将设备产生的状态信息存入状态寄存器中,供驱动程序查询。当有设备中断事件发生时,控制器发出中断请求信号,系统进入中断处理程序进行处理。

5.2  设备中断处理程序
  中断处理程序负责处理设备的中断事件,每个使用了中断的设备都有一个中断处理程序,如时钟中断处理程序专门处理来自系统时钟的定时中断,键盘中断处理程序专门处理键盘产生的中断。在CPU响应一个中断时,它会根据中断向量转去执行该中断对应的中断处理程序。
  中断处理程序与具体的设备密切相关,因此可以把它看做是设备驱动程序的一部分。不同之处在于,设备驱动程序是与I/O系统接口的,而中断处理程序是由中断系统调用执行的。

  中断处理程序的工作是对传输的结果进行必要的处理。需要指出的是,在中断处理程序执行过程中会关闭同一中断线上的中断请求,因此它必须尽快地完成工作,不然就会造成后续中断的丢失。此外,中断处理程序不允许被阻塞,因此它不能做任何会引起自己被阻塞的操作,如访问有竞争的资源,或调用某些会引起阻塞的函数等。这也是为保证中断处理能在限定的时间内结束。还有就是,中断处理程序运行在中断上下文中,也就是说它不与任何进程相关联,因此它不能访问用户进程的地址空间,向用户进程传输数据等。除此之外,中断处理程序与普通的C程序没有什么区别。

       6  Linux设备管理
6.1  Linux设备管理的特点
  Linux设备管理的最突出的特点就是设备独立性。这是指系统把设备统一当作文件来看待,只要安装它们的驱动程序,就可以像使用文件一样使用这些设备,而不必知道它们的具体存在形式和操作方式。
  之所以能够将设备作为文件对待,是因为
Linux文件的物理结构是字节流,而设备传输的数据也是字节流。如果将向设备输出数据看做是写设备操作,将从设备输入数据看做是读设备操作,就可以把读/写文件与设备I/O操作统一在一起,用同一组系统调用完成文件与I/O操作。设备独立性的好处是简化了I/O系统的设计,使系统结构简洁而高效,同时也方便了用户使用设备。

  并非所有的Linux设备都可以作为文件来处理。Linux系统将设备分为3类,即字符设备块设备网络设备。字符设备和块设备都可以通过文件系统进行访问,因为它们传输的是无结构的字节流,而网络设备则是个例外。网络设备传输的数据流是有结构的数据包,这些数据包由专门的网络协议封装和解释,因此需要经过一组专门的系统调用进行访问。Linux 设备管理通常指的是字符设备和块设备,本节也只介绍这两类设备的管理技术。

6.2  Linux系统的I/O软件结构
  实现设备独立性的手段是通过分层软件结构,把设备纳入文件系统的管理之下,使进程通过文件系统的接口来使用设备。图7‑9所示是Linux系统的I/O软件结构。
  
Linux系统的I/O软件采用两层结构设计,上层是文件系统,它负责设备的命名、保护、缓冲区管理以及设备分配等工作。在这个层面上,设备被抽象成了文件,设备的各种特殊性都被屏蔽了,用户可以像使用普通文件那样操作各种设备。下层是与设备相关的软件层,主要是设备驱动程序和对应的中断处理程序。

  用户进程使用文件系统的标准系统调用来打开、关闭和读/写设备文件。文件系统接受用户对设备文件的请求并进行相应的判别处理,然后将文件操作映射到设备驱动的I/O操作上,由设备驱动程序驱动控制器完成具体的I/O操作。

图7‑9  Linux 系统的I/O软件结构

  文件系统采用与文件相同的一套操作来实现设备的命名、保护与操作,这大大简化了系统的结构。对Linux系统来说,设备管理的主要工作实际上只是设备驱动而已。只要正确地实现了设备的驱动程序,就可以把设备纳入文件系统的管理之下。为此,Linux定义了文件系统与设备驱动程序之间的接口规范,任何设备的驱动程序只要遵守这些规范就可以与文件系统接口。接口方式既可以是静态的也可以是动态的。实际上,大多数设备驱动程序都是独立的内核模块,可以动态地加载和卸载。这种设计使得Linux 系统的I/O软件结构既简洁又灵活。

6.3  Linux的设备文件
  1. 设备的标识

  在Linux系统中,每个设备对应一个设备文件,设备文件一般都位于/dev目录下。用户用设备的文件名来指定设备,而内核则使用主设备号(major number)和次设备号(minor number)来标识一个具体的设备。一般来讲,主设备号标识设备的控制器,次设备号用来区分同一控制器下的不同设备实例。主设备号与设备的驱动程序一一对应,而次设备号供驱动程序内部使用。2.6内核的Linux系统支持高达4095个主设备号,每类主设备可以有多于100万个次设备号,这足以支持高端企业系统的设备配置。

  设备文件是一个特殊类型的文件,字符设备的文件类型为“c”,块设备的文件类型为“b”,设备文件的访问权限就是对该设备的访问控制。例如,下面的ls命令显示了软盘、打印机和硬盘文件的详细信息:
  $ ls  -l /dev/fd0 /dev/lp0 /dev/hda 
   brw-rw----  1  root  floppy  2, 0  May 12  15:13  dev/fd0
   crw-rw----  1  root  lp  6, 0  May 12  15:13 /dev/lp0
   brw-rw----  1  root  disk  3, 0  May 12  15:13  dev/hda
  $

  与普通文件的描述信息有所不同,设备文件的文件大小字段中显示的是主设备号和次设备号。在上面的输出信息中,/dev/fd0是软盘A驱动器的文件名,类型是块设备,主设备号是2,次设备号是0/dev/lp0是第一台打印机的文件名,类型是字符设备,主设备号是6,次设备号是0/dev/hda是第一个IDE磁盘驱动器的文件名,类型是块设备,主设备号是3,次设备号是0
  当对设备文件执行读
/写操作时,实际上实现的是对设备的I/O操作。例如,命令echo “Hello!” > /dev/lp0将会使打印机打印出一个字符串。

  2. 设备文件的描述
  同普通文件一样,每个设备文件也都有一个独立的i节点。不同之处在于,设备文件的i节点中没有指向文件存储块的索引表,而是通过主设备号和次设备号指明相应的设备驱动程序。
  与普通的文件一样,每个打开的设备文件也对应一个file结构、VFS i节点以及文件操作集file_operations(见图6-18)。不同之处在于,普通文件的file_operations中是标准的文件操作,而设备文件的file_operations中是设备驱动提供的一组专门针对该类设备的操作。VFS正是通过这个file_operations结构实现了将文件操作映射到驱动程序的操作函数上。

6.4  Linux设备驱动程序
  1. 驱动程序与内核的接口

  Linux系统的所有驱动程序都是内核的一部分,部分系统设备的驱动程序被静态地编译进内核,其余的驱动程序则是采用独立的内核模块的方式动态地加载到内核上。为了能与内核正确地结合,Linux对驱动程序的模块结构和接口都有规范的定义。
  
设备驱动程序与内核的接口是file_operations结构,它通过文件系统为用户进程和内核其他部分提供统一的接口,将对设备的操作通过文件系统映射到具体的设备驱动程序。

  file_operations提供的设备操作函数因设备的不同而有所不同,通常的操作有:
  ● open()    打开并初始化设备。
  ●
read()    从设备读数据。
  ●
write()    向设备写数据。
  ●
ioctl()    控制设备。
  ●  lseek()    定位读/写位置。
  ● release()  关闭设备,将其归还给系统。

  2. 驱动程序的功能
  不同设备的驱动程序在功能上会有或多或少的差别,但通常应包括以下几个。
  
1) 驱动程序的注册与注销
  注册是向内核登记驱动程序的信息,使内核知道该用哪个文件操作集来实现针对该设备的文件操作。注册的工作包括登记驱动程序(包括中断处理程序)信息、为驱动程序分配资源(内存与主设备号等)以及初始化驱动程序。驱动程序的注册是在系统引导或驱动模块加载时完成的。注销是注册的反操作,它解除驱动程序与内核的联系,释放驱动程序所注册的资源。驱动程序的注销是在系统关闭或者驱动模块卸载时完成的。

  2) 设备的打开与关闭
  和普通文件一样,设备首先要打开才能够进行读/写操作,完成操作之后也要及时地关闭。打开设备文件对应的操作是建立起文件系统到设备驱动程序的映射关系,并使设备准备好执行I/O操作。关闭文件对应的操作是释放这种映射关系、复位设备等,以确保下次可以正常打开和使用设备。
  文件系统提供的
open()和close()系统调用同样用于设备文件的打开和关闭,它将调用设备驱动的open()或release()操作,完成具体设备的初始化或复位操作。

  3) 设备的读/写操作
  进程使用read()write()系统调用来读/写设备,它们被映射到设备驱动的read()、write()或request()操作。在读/写过程中,针对不同的数据传输控制方式,驱动程序采取不同的管理方式实现具体的数据传输。

  4) 设备的控制操作
  对设备的控制操作通过系统调用ioctl()来完成。ioctl()的功能是向设备发出特定的请求,请求的含义及对应的操作与具体的设备相关,在各自的驱动程序中定义。例如,光驱的控制操作可以是弹出光盘,摄像头的控制操作可以是释放快门等。
 
 5) 设备中断的处理
  设备驱动程序需提供应对各种中断原因的中断处理程序。

6.5  字符与块设备的驱动技术
  1. 字符设备
  字符设备的驱动相对比较简单,主要工作包括注册、打开、操作、关闭和注销。
  
1) 字符设备的注册与注销
  系统启动时,初始化进程将调用各个设备驱动程序的初始化程序,执行驱动程序的登记和初始化任务。

  内核中设置了一个字符设备注册表chrdevs,每个注册了的字符设备驱动都在表中占有一个表项,以其主设备号作为散列索引来确定位置。驱动程序在向内核登记时,首先要指定或从内核获得一个主设备号,然后以此号为索引向字符设备表中添加一个表项。表项中name字段是设备的名字,fops字段是指向文件操作表file_operations的一个指针。file_operations表中保存了指向驱动程序提供的各个服务例程的函数指针。通过chrdevs表,内核可以掌握所有可用的字符设备以及它的可用的文件操作集。图7‑10是注册字符设备的描述结构。

图7‑10  字符设备的注册结构

  当驱动模块卸载时将执行系统的驱动注销函数。注销的操作主要是回收注册时分配给驱动程序的资源,包括主设备号和在chrdevs表中注册的表项。

  2) 字符设备的打开与关闭
  用户进程用open()系统调用打开设备。Open()系统调用的工作是:读取设备文件的i节点,建立它的VFS i节点以及file等对象(见图6-18);用chrdevs表中登记的文件操作集file_operations替换filef_op,然后将file连到当前进程的打开文件表file_struct(见图6-19);调用设备驱动的open()函数,设备的open()函数根据传来的i节点参数中的次设备号确定要打开的具体设备,检查设备错误并对其作初始化。至此,设备已准备就绪。

  用户进程执行close()系统调用来关闭设备。close()完成如下工作:释放该文件占用的fd等资源,将其file结构中的文件引用计数f_count1。若引用计数为0则释放file,并调用设备驱动的release()函数实际地关闭该设备。
 
 3) 字符设备的操作
  用户进程执行read()write()ioctl()系统调用来操作打开的设备文件,VFS的文件操作集file_operations将其映射到设备驱动的read()write()ioctl()函数,实现对设备的实际操作。对于只写设备(如打印机),它的read()函数是个空函数null()。同样,只读设备的write()函数也是空函数。

  2. 块设备
  块设备的驱动比字符设备的驱动要复杂得多,往往需要涉及到诸如缓冲、I/O调度、请求队列等相关技术。这一方面是因为块I/O与字符I/O的操作方式有极大的不同,另一方面是因为与字符设备相比,块设备的I/O效率对于系统的整体性能更为重要。

  1) 块设备驱动技术
  块设备与字符设备的主要区别在于块设备的操作是以块为单位的,因此需要经过缓冲区传输数据。为提高块设备的效率,Linux采用了缓冲区缓存(buffer cache)机制,所有对块设备的操作都要经过缓冲区缓存来进行。当用户进程需要读/写块设备时,它们实际执行的是缓冲区缓存的读/写函数。缓冲区缓存的读函数在缓冲区中检索数据,若命中就返回用户请求的数据,否则就请求设备执行实际的读出操作;缓冲区缓存的写函数将要写入设备的数据暂存在缓冲区中,在必要的时候再请求设备执行实际的写入操作。缓冲区缓存机制的好处是可以减少对设备的实际操作次数,提高进程的I/O速度。

  当实际执行块设备的I/O操作时,操作的执行顺序对I/O速度的影响很大。因为多数块设备(主要是磁盘)/写连续的扇区比分离的扇区速度更快。为提高I/O的效率,需要对操作顺序进行排序、调整和合并,以优化磁头移动性能。因此,Linux采用了请求队列和I/O调度策略。系统将对某个块设备的所有I/O操作请求排成一个队列,当缓存的读/写函数需要执行设备I/O操作时,它将调用IO调度程序对操作进行排序和合并,转换为一个请求加入到设备的请求队列中,等待处理。设备驱动程序逐个地处理请求队列中的各个请求,完成实际的设备I/O操作。由此可见,读/写块设备与读/写字符设备有着很大的不同。在读/写字符设备时,实际的硬件I/O一般紧接着就发生了,而读/写块设备时,实际的硬件I/O可能发生,也可能不发生或延时发生。

  2) 块设备的注册与注销
  Linux用块设备注册表blkdevs来登记已经注册了的块设备。blkdevs表的结构和作用与chrdevs表相似,也是使用设备的主设备号作为索引。当块设备驱动初始化时,它将通过填写blkdevs表向内核注册它的文件操作集。与字符设备不同的是,设备驱动还要为设备注册一个请求队列,它是驱动程序与缓冲区缓存的接口。请求队列的结构如图7‑11所示。

图7‑11  块设备的请求队列

  内核中为块设备的请求队列设置了一个blk_dev表,表的索引是设备的主设备号。每一个块设备驱动程序都要在blk_dev表中注册一个表项。表项中的request_fn字段是一个函数指针,它指向驱动程序提供的处理I/O请求的函数request()current_request字段是一个指针,它指向请求队列中的当前请求节点。每个请求节点代表了对块设备的一个请求,它是一个request结构,包含了一次块I/O操作的所有信息,如请求的状态rq_status、次设备号rq_dev、读/写命令cmd、开始扇区sector、扇区数nr_sectors、使用的缓冲区bh等。
  注销块设备时,需要释放驱动程序在blkdevs表以及blk_dev表中占有的所有资源。

  3) 块设备的打开与关闭
  打开与关闭块设备文件的操作与字符设备类似,只是在块设备的file结构中,f_op指向的文件操作集file_operations中的read()和write()不是由设备驱动提供的操作函数,而是系统提供的公共的缓存读/写函数。

  4) 块设备的读/
  块设备的读/写操作是通过缓存的read()write()公共函数进行的。当它需要启动设备执行I/O操作时,就通过I/O调度生成一个对设备的请求并将请求挂到设备的请求队列上。当请求队列不空的时候,系统将调用设备驱动在blk_dev中注册的request_fn函数来逐个处理请求队列中的各个I/O请求。驱动程序每次处理一个请求,将数据从设备读出到缓冲区,或从缓冲区写入到设备。请求完成后,系统将唤醒等待I/O的进程处理数据,驱动程序则继续处理下一个请求。

        习    题
  7-1 简述设备管理的基本功能。
  
7-2 什么是设备控制器?设备是怎样与I/O系统接口的?
  
7-3 I/O传输控制方式有哪几种?比较它们的优缺点。
  
7-4 什么是中断?为什么要引入中断?中断处理过程包括哪些步骤?
  
7-5 什么是DMA方式?简述DMA方式的数据传输过程。
  7-6 什么是缓冲?为什么引入缓冲?
  7-7 什么是缓存?缓存与缓冲有什么区别?

  7-8  什么是虚拟设备?实现虚拟设备的关键技术是什么?
  7-9  试说明SPOOLing系统的工作原理。
  
7-10  什么是设备驱动程序?它的主要功能是什么?
  
7-11  块设备与字符设备的驱动有哪些不同?
  
7-12  设备中断处理要完成哪些工作?Linux的设备中断处理有何特点?
  7-13  什么是设备独立性?Linux如何实现设备独立性?

di      

猜你喜欢

转载自blog.csdn.net/weixin_41939983/article/details/107484951
今日推荐