当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读]摘 要: 在Windows 98或Windows 95下如何高效编写硬件设备驱劝程序是微机应用开发中迫切需要解决的问题。介绍了虚拟设备驱动程序(VxD)在Windows 9X下运行的机理和通信策略

摘 要: 在Windows 98或Windows 95下如何高效编写硬件设备驱劝程序是微机应用开发中迫切需要解决的问题。介绍了虚拟设备驱动程序(VxD)在Windows 9X下运行的机理和通信策略,以及如何设计内核模式驱动程序。

关键词: 保护模式 VMM VxD DPMI

1995年Microsoft公司推出了其新一代的桌面操作系统Windows 95,从技术层面来看它是为发挥32位处理优越性能而设计的一个32位操作系统。而它出色的稳定性,强大的寻址能力,无不归功于对32位处理保护模式的充分应用。具体来讲,它利用了80386的保护机制,从操作系统到一般应用程序分别分到4个特权层上,操作系统享有最高的优先级,被安排在ring-0上运行,而优先级最低的普通应用程序被安排在ring-3上运行。这样做的好处是如果一般的应用程序在ring-3上崩溃将不会影响到ring-0的操作系统,另一方面也是对在ring-3上的应用程序所能访问到的资源做了一定的限制,从而大大降低了因应用程序直接操作而产生的意外错误。换句话说,在 Windows 98或Windows 95下,应用程序不能像在实模式下可以随意操作硬件资源,而需要通过编写运行在内核模式(ring-0)的虚拟设备驱动程序(virtual device driver)才能达到目的。因此,在Windows 9X下如何高效编写硬件设备驱动程序是微机应用开发中迫切需要解决的问题。

 

1 Windows 9X系统结构

确切的说Windows 9X不是一个操作系统,而是一个操作系统的集合。当计算机运行在保护模式下时,有“两个”操作系统同时存在,即Windows 本身和一个更低的操作系统,我们把它称为VMM/DPMI(virtual machine manager/Dos protect mode interface)。VMM的主要目的是管理同时运行的32位保护模式Windows应用程序(Win32 applications以及运行在虚拟86模式下的MS-DOS程序,前者称为“线程”(threads),后者称为VM(virtual machine)。VMM使每一条线程拥有自己的独立地址空间,使每一个VM都“单独”占有CPU,并为它们提供各种服务。从图1中我们可以看出,threads和VMs所能访问到的资源已不是直接的物理资源,而是被VMM虚拟化virtualized后的虚拟资源了。

另外,VMM是一个可扩充的“操作系统”,它的核心部件以及标准部件(比如,DMA控制器管理VDMAD,中断管理VPICD等)是由Microsoft 提供的。但我们可以编写一些扩充模块,也就是用VxD来增强VMM对硬件的虚拟能力,使整个操作系统获得对新硬件的访问能力。不仅如此,这种扩充操作系统的办法,还能为Win32程序与MS-DOS程序之间的通讯提供一种新的途径以代替传统的MS-DOS设备驱动程序以及内存驻留程序TSRs。从某种意义上说,没有VxD不能完成的事情,而且由于VxD是运行的保护模式下,所以它并不占有宝贵的常规内存。此外,运行实模式MS-DOS驱动程序所导致的模式切换也不复存在。因此一般来讲,VxD的运行速度要高出MS-DOS驱动程序一倍以上。更重要的是VxD在Windows 9X下可以动态装入与卸载而不需要重新启动计算机,这就大大提高了系统的灵活性,同时也为即插即用(Plug and Play)提供了可能。与实模式的驱动程序相比,可动态装、卸载可谓是一场革命。

2 VxD的结构及通讯策略

普通的Win32应用程序都是PE格式(Portable Exectable Format)的,而VxD则不同,它没有一般程序的进出口而是输出一种称作设备描述块DDB(Device Descriptor Block)的数据结构。它包括VxD设备ID、初始化顺序、Win32DeviceIOControl回调函数句柄、V86API句柄、PM API句柄等VMM在调用VxD时所需要的重要信息。此外,同其他应用程序一样,VxD由五个段构成,它们分别是:

(1)VxD_CODE段:保护模式代码段。该段包含VxD系统控制过程、回调过程、服务和API过程。

(2)VxD_DATA段:保护模式数据段。该段包括设备描述表、服务表和部分VxD全局数据。

(3)VxD_ICODE段:保护模式初始化代码段(可选)。该段一般包括只在VxD初始化过程中使用的过程和服务,VMM在Init_Complete消息发生后丢弃此段。

(4)VxD_IDATA段:保护模式初始化数据段(可选)。该段一般包括初始化过程和服务使用的数据,VMM在Init_Complete消息发生后丢弃此段。

(5)VxD_REAL_INIT段:实模式初始化段(可选)。该段包含实模式初始化过程和数据,VMM在装载VxD其它部分之前调用此过程,过程返回后丢弃此段。

当VxD装入内存时,VxD通常要靠DDB中所添入的一个16位的VxD设备ID,以区别于其它VxD。为了防止与其他新VxD冲突,Microsoft 通过请求和注册标识来保证自己的VxD设备ID没有被其它厂商使用,为此Microsoft保留0~01FFH之间的所有VxD设备ID供自己使用。

在编写VxD时首先要编写VMM的消息处理函数,以便作相应的处理。例如,在VxD装入内存时VMM对能动态装载的VxD发出 SYS_DYNMAIC_DEVICE_INIT消息,在要求卸载VxD时VMM又向其发出SYS_DYNAMIC_DEVICE_EXIT消息。在 VxD中只需编写相应的处理函数,便可达到设备初始化与卸载释放资源的目的。拿Win32程序来说,它使用CreateFile API函数打开可动态装、卸载的VxD时VMM便会发出SYS_DYNAMIC_DEVICE_INIT消息。相应的,当它使用CloseHandle API函数卸载VxD时VMM便会发生SYS_DYNAMIC_DEVICE_EXIT消息。

另外,在具体调用VxD中的函数时,也不像调用ring-3 DLL中的函数那样容易。我们以调用对象不同分以下几种情况讨论:

(1)从其他VxD中调用(ring-0调用ring-0)

当生成VxD时,所有可以被其他VxD调用的函数都列在一个数组里,我们称这种函数为一个服务(Service)、这个数组为服务项目表(Service_Table。在调用时,并不是用服务的名称而是直接使用该函数在数组中的索引号。例如对VMM中的1号服务 Get_Cur_VM_Handle

可采用如下格式:

int 20h

DD00010001h

32位的DD由两部分组成,它的高字包含了VxD设备的ID,低字包含了服务号(这里VMM的设备ID为0001h。

(2)从V86代码或Win16(保护模式)代码中调用?ring-3调用ring-0

这里应用程序要申请被调用的VxD函数地址,这个地址可以通过int 2FH/AX=1648h调用获得。为了识别是调用哪一个VxD的函数,调用时可令BX=VxD设备ID。当int 2Fh指令返回时,寄存器ES:DI(对保护模式有ES:EDI)包含一个seg:offset(对保护模式有selector:offset指针,调用该指针就可以把控制权交给运行在ring-0下的VxD

(3)从Win32代码中调用(ring-3调用ring-0)

事实上Microsoft隐藏了Win32的VxD服务接口,作为替代提供了Windows NT下的设备输入、输出控制(DeviceIOControl)Win32 API。Win32程序通过使用此函数向特定的VxD发送控制码与数据。与此相应在编写VxD时要提提供一个相应的回调函数以响应它所发出的 W32_DeviceIOControl消息,并再去回调函数中响应相应的控制码,最后还要把该回调函数的句柄添加到DDB中。它的定义如下:

BOOL DeviceloControl(

HANDLE hDevice,//用CreateFile API函数打开VxD设备获得的句柄

DWORD dwloControlCode,//ring3程序向VxD传递的命令码(可由编程写者自定)

LPVOID lpOutBuffer,//程序传给VxD的数据缓存的地址

DWORD nlnBufferSize,//ring3程序传给VxD的数据缓存的字节数

LPVOID lpOutBuffer,//VxD的返回数据所存放的缓存地址(该缓存由ring-3预留)

DWORDnOutBufferSize,//VxD的返回数据所存放的缓存的字节数

LPDWORD lpBytesReturned,//VxD实际返回数据的字节数

LPOVERLAPPED lpOverlapped //一个OVERLAPPED的结构地址,通常为NULL);

由此不难看出这种DeviceIOControl的结构也为VxD向ring-3回传数据提供了一种途径。这种通讯方式在NT的设备驱动程序中也得到了广泛应用,它是Microsoft大力提倡的Win32程序应采用的一种通讯方式。

3 VxD的实现

从编程工具方面来看,我们需要Windows 95 DDK和一个32bit的汇编编译器,如MASM6.11c,如果打算用C/C++开发驱动程序的话,还应选用一个32bit的c/c++4.0编译器,笔者推荐采用Micrfoft Visual C++4.0以上的版本,因为它支持一种新的关键字——declspec(naked) 。采用该关键字的函数,编译器将不为其生成相应的函数进出口代码,这样对于采用特殊函数结构的VxD函数来说是非常方便的。除此之外,也有一些公司提供了一些VxD向导器以帮助用户生成C/C++的程序框架,使用它们可以大大提高开发效率,应予以考虑,其中最著名的有 Vtoolsd95,VxDwriter等。在编程中应注意,不要使用C/c++所提供的库函数,特别是Microsoft的MFC,因为它们都是运行在 ring-3上的,如果非用不可的话,只有一些个别函数能通过使编译器生成嵌入式指令来达到目的,但这样做是要相当小心的。另外,调试运行在ring-0 的驱动程序是相当困难的,VC++以及MASM中的调试均不能满足需要,而需采用内核级的调试工具比如Microsoft的WDEB386以及 Numega的SoftIce等。

4 VxD的局限性

VxD技术只适用于Windows 9X操作系统,Windows NT不支持此项技术,而是采用更为先进的面向对象的驱动程序模型,例如Windows 98和Windows 2000就采用了一种基于NT的驱动程序模型WDM。此外,由于VxD运行在ring-0上根本不受ring-3的制约,也给病毒的制造者即黑客以可乘之机,比如著名的CIH病毒是一个VxD。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭