精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>技术精解:内存、进程、线程等>>从vxd到vxd

主题:从vxd到vxd
发信人: dunhill()
整理人: wenbobo(2002-12-06 22:56:22), 站内信件
Windows 95下的虚拟设备驱动程序 

虚拟设备驱动程序(VxDs)在很大程度上支持了Windows 3.x 和Windows 95。
通常,我们从 两个级别的意义上来认识VxDs:从低级意义上来说,它们直接
存取系统的硬件;而从高级意义 上来看,它们在最高优先级别上运行。 

在Windows 95中,VxDs显得更加重要,Microsoft正是靠VxDs扩展了操作系统
内核的处理 能力。Win 95中的VxDs可以处理涉及从文件系统到声卡以至网
络系统的各种事务。 

可能您还未认识到:  尽管VxDs本身是32位的, 但它却诞生于16位的非线程、
非抢占性的操 作系统。而现在人们期待甚至要求VxDs能运作于具有线程化、
可抢占性的操作系统,简单的 变形是不能解决此问题的。 

虚拟机假想 

一台虚拟机(VM)只不过是人们的一个假想。而特别的,这个假想认为一个给
定的进程可对一台计算机的所有硬件设备进行独占性的存取,这些设备包括
了内存、I/O口、中断和其它 进程想要占用的部件。 VxDs就是为了此假想
产生的。 

Windows 3.1中有两种虚拟机(VMs): DOS壳和Windows VM本身(后者称为"系
统虚拟机"———所有的Windows 应用程序运行于其中)。 而虚拟机管理器
(VMM),  尽管它本身不是一 VM, 但却充当着激活 VMs和VxDs的主要管理员。
例如,VMM要处理在运行VMs时的抢占时间片工作。 

另外, 任何用来虚拟管理I/O设备的VxD都必须在VMM中登记。因此, 如果一
VxD要占用一些特殊的I/O端口,就必须请求VMM挂起这个端口。这样,无论何
时当一Windows应用程序试图对 此口进行存取操作时, VMM将把这个存取请
求传给特定的VxD。 

在Win 95中这样的情况基本相同,但做得更好。仍然是DOS壳作为一VM,所有
的Windows进 程作为一VM。但这些进程包含了一些比Windows 3.x中的Win32s
程序具有更强能力的Win32应 用程序。 

这就产生了一些VxD设计者必须清楚的新问题。例如, Win 95中的Win 32应
用程序可以是 多线程化的,一个VxD不再只知道是哪一个VM请求服务, 有时
一个VxD还必须知道是哪一特定V M中的哪一个线程需要服务。 

顺便提一下, 也许一些读者和我最初一样认为每一个Win 32应用程序在Win
95中就是它自己的VM,  而事实上是, 尽管它们有自己的地址空间, 每一个
Win32应用程序却只是系统VM的一个成员。 

更重要的是, Win95中的一个成功的VxD应该是既可与新的32位Windows应用
程序协作, 也可与过去的 16位Win-dows应用程序协作运行。这就使得VxDs
有些不同起来。 

过去的方法 

尽管VxDs可以通过挂起I/O口和执行中断等其它高优先级事件来虚拟硬件设
备, 但这只是它为应用程序做的一部分事务。VxDs还可以提供可调用的APIs,
使得一个应用程序可以直接 申请VxD服务。 

在Windows 3.x里,我们可以通过中断2FH来得到一个VxD的API(限于篇幅,这
里不再多言)。这种机制在Win 95中可以通过 16 位应用程序来有效地使用。
实际上,Win 95有一点变化: 将BX寄存器设为零,并在ES:DI寄存器对中存放
一指针而不是从BX寄存器中调用设备号。这个 指针指向VxD的名字,它是一
个八位长的大写字符串。和以前相同的是,在程序执行INT 2FH指 令后,VxD
的API地址返回在ES:DI中。 

糟糕的是,INT 2FH技术并不适用于Win32应用程序。实际上,Win32应用程序
不能执行软 件中断。 

对我们来说,这是否意味着Win32应用程序和VxDs处于不可跨越的裂缝中?答
案是否定的 ,我们仍可用VxD代表32位应用程序来虚拟I/O端口, 只是在VxD
将API地址提交给Win 32程序时 有些麻烦。但这也不要紧, VxD既提供了16
位API又提供了32位API, 这使得在 Win 95环境下16 位Windows应用程序与
Win 32应用程序一样重要。 

新的VxD 

无论何时, 当一个VxD必须处理的事件发生时, 就有一条控制消息传送给VxD。
这些消息来自VMM或其它的VxDs, VxD处理它们就像Windows程序处理Windows
事件一样。通常,这些消息告 诉VxD:"一应用程序正试图存取你管理的I/O口,
有消息来……注意"。 

Win 95添加了一条新消息W32-DEVICEIOCON-TROL, 这条消息是在一个Win 32
应用程序调用DeviceIo-Control()函数时发给VxD的。这就是一Win32应用程
序可直接调用VxD的机制。 

对Win32应用程序来说, 它必须首先调用CreateFile()函数得到一特定VxD的
句柄。通常这函数是用于创建打开磁盘文件的,但如果程序在调用它时,给文
件名前加上前缀\\.\,系统 就会识别出此文件名是对应于一VxD名。(当然在
C/C++中,字符串中的反斜杠字符必须加更多 的反斜杠前缀,因此\\.\就成了
\\\\.\\.) 

函数CreateFile()返回一句柄,这里是一个VxD的句柄。应用程序可用这个句
柄调用函数 DeviceIoControl()来发消息给VxD。(调用函数DeviceIoControl()

实际上调用了一个中间V xD:VWIN32,它再调用代表应用程序的VxD) 

函数DeviceIoControl()提供了通知VxD执行何功能的参数, 同时提供用于在
应用程序和 VxD间传送数据的输入输出缓冲区指针。 

动态VxDs 

使用函数DeviceIoControl()与VxD通讯还有另外一个好处。在Win 3.1中VxDs
是静态装 载的,也就是说,当Win-dows启动时要装载所有要用的VxDs,它们将
在Windows执行生命期间一 直处于活动状态。 

Win 95(以及Windows for workgroups 3.11) 却允许动态装载卸下VxDs。当
一应用程序 用CreateFile()函数存取一VxD时,系统会跟踪每个VxD打开了多
少句柄。当应用程序终止时 ,它要调用函数CloseHandle()释放这个VxD打开
了多少句柄。当应用程序终止时,它要调用函 数CloseHandle()释放这个VxD
的句柄, 这就减少了系统打开的句柄数。 (有一点很重要,当一 进程消亡时,
与其相联的句柄会被自动调用) 

只要一 VxD 的句柄数减到零, 系统会给这个 VxD 发送一条控制消息  SYS-
DYNAMIC-DEVICE-EXIT, 告诉它:"你即将被卸下,……请消除一切"。VxD在处
理完这条消息后,系统就卸下它。 

一点补充说明 

当然,VxD设计者还没有做到尽善尽美, 他们还必须设置另外的事件处理程序
来处理W32- DEVICEIOCONTROL消息。尽管为了利用VxD的API而单独创建一条
途径似乎有些令人难受,但随着Win 32程序数量的增多,我们会发现这条路并
不难走。实际上,我们并不需要做太多的事。 VxD在俘获由VMM发来的消息时
已有一个控制-分发事件处理程序例程。只要我们写出处理W3 2-DEVICEIOCONTRO
L
消息的事件代码, 剩下的只是在将事件代码与事件处理程序例程相匹配的跳
表中增加一个入口而已。 

一句话,有了DeviceIoControl()调用机制,VxD将在Win 32应用程序中起到重
要作用。 

 

--
我是一沙鸥,天地任遨游。飞到昆仑边,飞到海尽头。
狂风我不怕,烈日我不愁。笑看黄鹂鸟,檐头意踌躇。

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.75.46.91]

[关闭][返回]