WIN95下虚拟设备驱动程序设计开发

2006-05-07 15:50:05来源: 电子技术应用

      摘 要: 介绍虚拟设备驱动程序开发的基本知识以及VxDs与WIN32应用程序通讯的几种常用方法,并给出了用VtoolsD开发VxDs的具体实例。

    关键词: 虚拟设备 虚拟设备驱动程序(VxDs)DDK VTOOLSD   

    Windows自面世以来,即以其强大而友好的图形界面占据了操作系统(尤其是微机操作系统)的霸主地位。但是由于Windows采取的保护措施屏蔽了系统的底层操作,对用户而言,已不能象在DOS下一样直接操纵使用系统的硬件资源如内存、I/O端口、中断及DMA等。这在很大程度上保证了操作系统的安全稳定性能,但却给广大硬件及底层软件开发人员带来了困难。当需要直接操纵控制具体的硬件设备时,往往需要编写设备驱动程序。

    1 VMM、VNMs和VxD

    Win95操作系统支持多线程、多任务应用,正是依靠虚拟机管理器VMM(Virtual Machine Manager)和虚拟设备驱动程序VxDs(Virtual Device Drivers)一起来实现设备虚拟化,从而使多个应用能够同时执行。设备的虚拟化是建立在虚拟机假想的基础上的,假想认为每一个VM都可以对所有的硬件设备(如内存、I/O端口、中断等)进行独占的控制,就如DOS下的应用程序一样。VxDs即为实现此假想而产生。

    Windows中有两种虚拟机VMs:DOS VM和System VM。每运行一个DOS程序将产生一个DOS VM,即不同的DOS程序运行在各自的DOS VM中,而所有的Windows应用程序(包括WIN16和WIN32应用)都运行于系统虚拟机中。每个VM有自己的地址空间、I/O端口、中断向量表,VM为应用提供内存保护、虚拟内存和权限检查等,只是在WIN16中应用程序运行在同一地址空间中,而每个WIN312应用程序都拥有自己的地址空间。所有的VM都接受VMM的统一调度管理,虽然VMM本身不是一VM,但却充当着激活VMs和VxDs的主要管理员(例如,VMM要处理在运行VMs时的抢占时间片工作)。VMM是操作系统的核心,VMM提供单线程、抢先多任务处理。它是一个32位保护模式操作系统,它的主要任务是产生、运行、控制和终止虚拟机VMs,它让多个VMs共享CPU的时间以使多应用能同时运行,其实VMM本身即是一些VxDs的集合,VMM不可重入。

    VxDs在很大程序上支持Windows 3.X和Windows 9X,可以将它看作是运行在系统特权级上的特殊的DLL,VxDs可直接操纵系统的硬件资源,甚至可以虚拟根本不存在的硬件,Windows利用虚拟设备来管理软件及硬件设备以确保应用程序不互相干扰。大多数虚拟设备用来管理硬件设备,有些虚拟设备也提供软件服务,而不对应于具体的硬件设备。如1999年初猖狂蔓延的CIH病毒,之所以能破坏硬件资源(通过攻击主板的Flash Memory,达到破坏硬件的目的),正是因为它利用了VxD技术,运行在系统Ring 0级。

    在Win3.X中VxDs是静态装载的,也就是说,当Windows启动时要装载所有要用的VxDs,它们将在Windows执行生命期间一直处于活动状态,Win9X(以及Windows for workgroups 3.11)在支持静态VxDs的同时允许动态装载卸下VxDs。当一应用程序用CloseHandle()函数存取一VxD时,系统会跟踪每个VxD打开了多少句柄。当应用程序终止时,它要调用函数CloseHandle()释放这个VxD所打开的句柄。当应用程序终止时,它要调用函数CloseHandle()释放这个VxD的句柄,这样即在需要时加载相应的VxD、用完后卸下,提高了系统资源的利用率。当然在进程消亡时,与其相联的句柄会被自动释放。

    VxD处理硬件设备时一个经常用到的硬件资源就是硬件中断,VxD处理硬件中断时,虚拟设备很少直接截取中断,而是依赖虚拟可编程中断控制器(VPICD),VPICD实现了物理可编程中断控制器(PPIC)的虚拟化,VPICD发送硬件中断信号给其他虚拟设备,并向虚拟设备提供请求中断、模仿硬件中断等服务。

    2 VxD设计开发

    2.1 开发工具

    开发VxD需要专门的开发工具,目前应用广泛的工具主要有两大类,一类是Microsoft提供的对应于不同版本的Windows的DDK(Device Driver Kit),其中包含了开发VxD所需的各种类库及汇编工具等。由于用DDK开发VxD大多使用汇编语言,所以开发起来相对比较困难。另一类是Vireo Software提供的Vtoolsd,VtoolsD开发包提供了对VxD编程的全线C++类库支持,利用VtoolsD中的Quick VxD工具可以快速生成VxD的代码框架,开发者可以在此基础上根据各自的需要添加自己的代码,使用VtoolsD可以不需要DDK。比较而言,使用VtoolsD要比使用DDK简单、快捷。另外,由于VxD运行在Ring()级,开发VxD时好的调试工具也很重要,常用的有NuMega公司的SoftICE和Microsoft公司的WDEB386等。

    2.2 VxD与WIN32应用间的通讯

    运行在系统特权级的VxD在处理系统底层设备的同时,大多要为上层应用程序提供服务或调用,于是VxD与应用程序之间的相互通讯在设计开发过程中显得尤为重要。VxD与应用程序之间的通讯包括从VxD到应用程序和从应用程序到VxD的双向通讯。WIN32应用程序可以通过调用DeviceIoControl函数向VxD发送W32_DeviceIoControl消息,VxD中的消息处理函数onW32DeviceIoControl处理此消息,其中消息参数可用来传递双向信息。反过来,由VxD向应用程序的通讯就相对复杂得多,其中常用的几种方法有(以下的应用程序皆指WIN32应用程序):

    a.使用SHELL服务Shell_PostMessage或Shell_CallAtAppTime等。Shell_CallAtAppTime使得系统在应用程序时间事件触发时调用事先设定的Ring3回调过程,此方法可用来调用动态链接库DLL中的函数,并且Shell_CallAtAppTime可以在中断处理时调用;Shell_PostMessage可以用来从VxD中向Ring3应用发送消息,此方法简单实用,只是发送给应用程序的消息因处于线程的消息循环中可能造成一定的时延,Shell_PostMessage不能在中断处理时调用,替代的方法是在全局事件(GlbalEvent)函数中调用Shell_PostMessage向Ring3应用程序发送消息,需要传给VxD的有消息处理窗口句柄及消息标识。

    B.使用APC(asynchronous procedure call)异步过程调用。使用APC调用方法,应用程序将回调函数的地址传给VxD,然后应用程序执行SleeepEx(或WaitForMultipleObjectsEx、WaitForSingleObjectEx)使其处于警觉等待(alertable wait)状态,这样当VxD调用VWIN32_WaitSingleObject服务时即可触发Ring3应用的回调函数,同样此服务不能在中断服务中调用,但可以在事件服务中使用。

    c.使用WIN32事件。WIN32事件在多线程应用程序中很常见,主要用来在多个线程间实现通讯和资源同步。这一方法同样可以用来在VxD和Ring3应用程序间通讯,在VxD中利用VWIN32_ResetWin32Event、VWIN32_SetWin32Evevn、VWIN32_WaitSinglezobject等服务来对特定的事件进行控制,从而唤醒等待的WIN32应用线程或者等待被应用程序唤醒。应用程序可用一子线程来等待VxD的事件,其使用方法类似于应用程序中的多线程处理,只是VxD和应用程序分别使用的是Ring0级和Ring3级事件句柄,所以应用程序不能直接将应用级事件句柄传给VxD,而是要用WIN32API函数OpenVxDHandle将应用级事件句柄转换成VxD级事件句柄,然后将此句柄传给VxD使用。由于OpenVxDHandle函数是未公开的API,所以使用时涉及到DLL的调用等稍微复杂的方法。

    以上是VxD与WIN32应用程序通讯的几种主要方法,但在开发中断处理VxD时则要注意,由于硬件中断是异步事件,必须遵守中断处理的各项规则,硬件中断处理时系统服务要慎用,当然可以在VxD的硬件中断事件处理函数(Hw_Int_Proc)中使用全局事件,或者在虚拟中断处理函数(Virt_Int_Proc)中使用适当的方法来实现。

    2.3 VxD开发实例

    下面给出一个用VtoolsD开发的虚拟设备驱动程序的实例。该驱动程序用来处理中断irq10,使用APC异步过程调用的方法实现VxD和WIN32应用之间的通讯。当中断发生时触发全局事件,在全局事件处理函数中使用APC方法VWIN32_QueueUserApc来调用Ring3级应用过程,在Ring3级的APC过程中可根据需要编写相应的处理代码。该VxD是一动态加载的驱动程序,WIN32应用需要传递给VxD的主要参数有APC过程的指针。在WIN32应用中可以创建一线程专门用来处理与VxD的通讯等事务,通过DeviceIoControl函数将APC过程的指针传给VxD,尔后线程SleepEx即可。My.vxd的部分源码如下。

(1)My.h - inchde file for VxD My

#define My_IRQ 10//IRQ中断号

class MyHwInt:public VHardwareInt

{

public:

    MyHwInt:public VHardwareInt(MY_IRQ,VPICD_OPT_CAN_SH_

    ARE,0,0){}

virtual VOID OnHardwareInt (RMHANDLE);

};

class MyDevice:public VDevice

{

public:

virtual BOOL OnSysDynamicDeviceInit();

virtual BOOL OnSysDynamicDeviceExit();

virtual DWORD ONw32DeviceIoControl(PI-

OCTLPAR-

AMS pDIOCParams);

MyHwInt*pMy IRQ;

};

class MyEvent:public VGlobalEvent

{

public:

MyEvent(VOID);

VOID  handler  (VMHANDLE  hVM,CLIENT_STRUCT*pRegs,,PVOID refData);

};

(2)mY.cpp-main module for VxD My

PVOID OpenFileApc=0;  //APC过程指针

THREADHANDLE TheThread=0;//Ring0线程句柄

MyEvent::MyEvent(VOID):VGlobalEvent(0){}

VOID MyEvent::handler(VMHANDL3E hVM,CLIENT_STRUCT*

pRegs,PVOID refData)

{ // 事件处理函数

VWIN32_QueueUserApc  (OpenFileApc,0,

TheThread);

//异步过程调用

};

VOID  MyHwInt::OnHardwareInt  (VMHANDLEhVM)

{

(new MyEvent())→call(); //全局事件调度

sendPhysicalEOI(); //通知VPICD中断处理结束

}

BOOL MyDevice::OnSysDynamicDeviceInit()

{

pMyIRQ=new MyHwInt();

VEvent::initEvents();//初始化事件堆

return TRUE;

}

BOOLMyDevice::OnSysDynamicDeviceExit()

{

delete pMyIRQ;

return TRUE;

}

DWORD MyDevece::OnW32DeviceIoControl(PIOCTLPAR

AMS p){     //与Win32应用程序的接口函数

switch(p→dioc_IOCtlCode)

{

case 111:

OpenFileApc=*(PVOID*)p→dioc_InBuf;

//从WIN32传入的APC过程指针

TheThread=Get_Cur_Thread_Handle();

//获得Ring级线程句柄

PMyIRQ→hook(); //挂接中断

pMyIRQ→physicalUnmask();//解除中断屏蔽

break;

}

retum 0;

}

 

 

 

 

编辑: 引用地址:http://www.eeworld.com.cn/designarticles/network/200605/2929.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
论坛活动 E手掌握
微信扫一扫加关注
论坛活动 E手掌握
芯片资讯 锐利解读
微信扫一扫加关注
芯片资讯 锐利解读
推荐阅读
全部

小广播

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 安防电子 医疗电子 工业控制

北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2016 EEWORLD.com.cn, Inc. All rights reserved