Windows内核原理与实现之Windows I/O软件技术

从操作系统角度而言,I/O软件的模型应该是设备无关的,因而,系统可以支持各种设备,甚至是未来出现的设备。针对I/O设备的软件模型必须有足够的通用性,至少能够将上节介绍的各种I/O硬件特性涵盖到模型之中。另外,操作系统必须提供有效的管理手段,从而让设备的软件组件融入到系统的I/O处理框架中,这样,这些软件可以专注于针对特定设备的功能需求,而不必过多地考虑与系统打交道或者与系统中其他模块的协作。例如,针对磁盘读写的软件组件无须考虑磁盘上的文件系统。

设备的软件组件通常称为设备驱动程序,或简称驱动程序。设备驱动程序或者由设备的硬件厂商提供,或者由操作系统厂商提供。由于设备驱动程序直接与硬件打交道,它们需要一定的特权才能操纵硬件设备,所以驱动程序通常运行在处理器的特权模式下,其代码与操作系统的内核代码享有同样的特权。这种设计的一个潜在后果是,驱动程序中的错误可能会导致整个操作系统奔溃。因此,驱动程序代码往往需要经过精心的设计、检查和调试,其代码规模应尽可能地小。从代码功能划分的角度来考虑,应尽可能把代码逻辑移到应用程序中,而让驱动程序只做最必要的事情。

与设备关联的驱动程序,其最基本的功能是,将操作系统的功能请求,解释成针对该设备的请求,然后操纵设备以完成该请求,最后将结果以指定的方式返回给调用者。在此过程中,有些事项往往是驱动程序必须要考虑并解决的。下面逐一讨论。

首先,与设备的通信是同步或异步方式。从软件控制流的角度,同步方式的通信容易实现,而且错误处理和恢复也相对容易。若一个I/O请求是异步方式,则处理器向硬件发送请求以后,其指令流返回到上一级调用代码,此I/O请求被搁置起来,处理器的指令流转而执行其他不依赖于此I/O请求结果的任务。当设备或设备控制器完成了该请求(比如DMA数据传输)以后,它中断处理器的当前指令流,报告该请求的完成情况。处理器必须在中断处理过程中将原先被搁置的I/O请求接手过来,继续该请求后续的处理。

异步方式的通信虽然复杂,但是可以提高处理器的利用率,因而在现代计算机系统中被广泛地采用。因此,设备驱动程序除了要操纵设备控制器,还必须引入中断处理代码,以完成异步通信的后半部分任务。Windows提供了一套中断分发机制,允许设备驱动程序在不操纵处理器的IDT的情况下,向系统中增加中断服务例程。而且,在中断处理过程中,一些不那么紧急的任务可以放到DPC中完成,从而缩短处理器停留在高IRQL上的时间。

在设计I/O驱动程序时另一个往往要考虑的问题是缓冲区管理。不同设备对于数据传输的效率有不同的要求,譬如,实时性要求高的软件或设备应尽可能减少数据拷贝的次数;驱动程序为了提高设备的I/O的吞吐量,可能会将数据缓存起来,而不是立即发送。有些设备要求直接使用物理内存地址;有些设备驱动程序直接使用应用程序提供的缓冲区以减少数据拷贝次数。驱动程序的缓冲区管理相对比较复杂,尤其采用了异步通信方式以后,缓冲区作为一种有限的资源,更需要谨慎的设计和管理,以避免资源泄露或不恰当地重复使用。

另一个值得提及的问题是共享和独占设备。在现代操作系统中,设备作为一种公共资源,通常是多个程序甚至多个用户所共享的。譬如,机器上的硬盘往往是系统中所有用户共享的,任何活动的应用程序只需有权限许可,都可以访问它们。对于磁盘设备驱动程序而言,每个程序的硬盘I/O请求都是独立的,这些I/O请求可以并存。然而,对于有些设备,比如打印机,一个应用程序必须以独占方式使用该设备。并发地响应两个应用程序的打印请求,将会导致无效的打印结果。

除了传输数据,设备驱动程序另一项重要的职责是设备的状态管理,包括设备初始化、即插即用、电源管理以及错误处理等。其中即插即用和电源管理是操作系统设备管理的一个重要任务,这些特性对于现代通用型计算机系统具有重要的意义。设备驱动程序必须在操作系统提供的管理框架下,达到设备状态与系统状态一致。错误处理应尽可能在下层软件(比如设备驱动程序)中完成,从而避免错误扩散到上层应用软件,这样也可以简化上一层软件设计。

接下来我们看操作系统如何为驱动程序提供一个环境。首先,设备驱动程序中的各种实体、包括设备、驱动程序本身,需要有一套标识方法。常见的做法是定义一个名字空间,因而操作系统或者应用软件可以方便地命名与设备有关的各种实体。Windows和UNIX都使用了字符串形式的名字空间。

设备驱动程序与操作系统之间是互补关系。设备驱动程序为操作系统提供了必要的访问硬件设备的能力,同时也依赖于操作系统提供的软件功能,比如,内存管理、错误处理、同步互斥机制等。图6.3显示了两者关系,对于多种设备通用功能,操作系统尽可能在统一的系统模块中实现,比如同一总线上的设备共享总线协议,相同类型的设备共享许多基本特性。这种设计的好处是,设备驱动程序中的代码量可以尽可能地少,从而减小给操作系统带来不稳定因素的可能性。而且,这些可被多个设备共享的功能可以由操作系统厂商或其他专门的厂商来提供,他们可以比单个设备厂商投入更多的资源来实现并测试这些系统模块。

Windows内核原理与实现之Windows I/O软件技术_第1张图片

现代计算机系统中,诸如即插即用、电源管理等特性越来越重要,操作系统的职责是提供一个符合即插即用和电源管理工业标准的软件框架。为了支持计算机系统的即插即用特性,操作系统自引导时开始,就将自动检测设备是否存在,并协调和分配相关的资源(比如中断、I/O端口地址);以后在系统运行过程中,继续管理这些设备的状态,包括动态地挂载和卸载设备,甚至升级驱动程序。同样地,电源管理也是一项需要软件和硬件紧密配合才能行之有效的特性,当操作系统接收或检测电源状态变化时,它负责通知设备驱动程序,由驱动程序来确定设备的电源状态。简单来说,操作系统负责发送电源命令,而设备驱动程序负责实施电源命令,并向操作系统反馈设备的电源状态。

最好看一下用户程序中的I/O操作,通常,用户程序调用操作系统提供的系统服务来完成I/O功能。譬如,C语言程序常常通过C运行库的printf/scanf函数来完成基本的I/O任务,这些函数可以把用户程序中的I/O请求转变成针对特定设备的I/O命令。虽然用户程序不能直接操纵设备,但是,它们通过操作系统提供的服务,可以共享或独占使用I/O设备。在实践中,操作系统的全局名字空间往往使得用户程序指定特定的设备非常方便。此外,让用户程序通过系统层的服务来访问设备,还有另一方面的好处,即操作系统可以提供虚拟的I/O设备或者用软件来模拟硬件设备。例如,操作系统可以利用网络功能来模拟大容量存储设备,从而使应用程序无须额外的努力方便可以访问远程存储设备。

你可能感兴趣的:(Windows内核驱动)