发信人: chenjr()
整理人: smallhors(1999-07-22 22:58:34), 站内信件
|
基于Windows软件平台的应用的迅速普及,使得开发DOS驱动程序与
Windows应用程序接口的需求日益迫切。本文介绍了实模式DOS设备驱动程序访问
Windows保护模式进程动态申请的数据段,实现处于DOS与Windows不同工作模式的 进
程之间的通信的一种方法。
关键词 进程通信 保护模式 实模式 DOS Driver DPMI
随着计算机硬件的快速发展,功能强大的Microsoft Windows得到越来越广泛 的
应用,软件环境由Windows替代DOS是大势所趋。增强模式的虚拟设备驱动棗序桘 繍
VxD(.386文件)是人们能够编写的最强大的Windows应用程序,但却它是Windows编 程
中一个艰难且高度专业化的分支,而且一般用户应用程序独享自制外部设备硬件 资
源。Windows 3.x采用非抢先式多任务消息驱动运行机制,所以Windows下如何解 决
实时高速数据采集问题,便显得非常重要。Windows 3.x应用程序虽然可以运行在 保
护模式下,享有多于1M的内存,但它并未脱离实模式的DOS。在实时获取和控制系 统
中,为快速响应外界变化而编写DOS设备驱动程序是简单而有效的选择。显而易见 ,
必须解决实模式的DOS设备驱动程序与保护模式的Windows进程之间的通信问题。
Windows API
能否既充分利用Windows统一、美观的交互界面,又能够保障数据采集的实时 性
呢?答案是肯定的。利用Windows提供的DPMI(DOS保护模式接口)功能,以及内核 函
数GlobalDOSAlloc(),就可以实现由DOS设备驱动程序直接访问Windows应用程序 动
态申请的缓冲区的目的。这个函数可以分配既能够被Windows应用程序存取,也能 被
DOS 设备驱动程序访问的内存块。
Windows 3.x通常运行于386增强模式,亦即对应着DOS环境下的保护模式。在 增
强模式下,由于增加了虚拟内存管理,由描述符表(GDT和LDT)得到的线性地址与 物
理地址之间并没有必然的联系。它们之间只有一种类似于表格的对应关系,所以 需
要利用DOS保护模式接口(DPMI)来完成这项工作。
①DWORD GlobalDosAlloc(cbAlloc)棗在 GWindows环境中分配一块能在MS- DOS实 模
式下管理的全局内存。
DWORD cbAlloc; /* 指定要分配的内存字节数*/
函数GlobalDosAlloc()分配的内存保证位于第一个1M线性地址空间之内。因 为
系统内存池是极为有限系统资源,所以,应用程序都应尽量压缩该函数所申请的 内
存尺寸。函数返回值的高字是段值,而低字是相应的段选择符。DOS Driver可以 利
用段值访问实模式内存,而Windows应用程序则利用段选择符访问保护模式内存。 如
果Windows不能分配所要求大小的内存块,将返回零值。
注意:通过GlobalDosAlloc()函数分配的内存空间不需要象通常进行数据存 取
那样,使用GlobalLock()函数来锁定该段内存空间。
②UINT GlobalDosFree(uPMSelector)棗释放前面由sFGlobalDosAlloc函数分配的
全局内存对象。
UINT uPMSelector; /* 待释放的内存段选择符*/
③WORD HIWORD(DWORD dwInteger)棗取出参数(DdwInteger所指定的32位整数值的
高字。
④WORD LOWORD(DWORD dwVal)棗取出参数VadwVal所指定的32位整数值 的低字。
程序设计
下面列出的程序展示了具体的实现过程,它通过调用Windows内核函数
GlobalDosAlloc()申请内存块作为与DOS Driver进行通信的缓冲区。设备驱动程 序
DOSDRV.EXE挂接中断77h(对应IRQ15),既可以等待来自硬件的中断,数据采集完 成
之后,向Windows应用程序WINCOMM.EXE发送消息,通知其进行数据接收和处理; 又
可以由Windows进程向DOS Driver发出服务请求,自主地完成数据的获取。
由于程序篇幅较长,下面只列出关键部分,并加以说明。
Ⅰ.DOSDRV.ASM:
①DOS Driver安装检查
入口:
AX = 通信印鉴
BX = 0
出口:
BX = 通信印鉴
②DOS Driver数据处理
入口:
AX = 通信印鉴
BX = 1
CX = Segment => WORD
DX = Offset => WORD
name dosdrv
Vect_Num equ 77h
Int_Flag equ 1234h
_TEXT segment word public 'CODE'
assume cs:_TEXT,ds:_TEXT
oldint dd 0 ;原中断向量地址
handle proc
[push ......] ;保护现场
cmp ax, Int_Flag ;鉴别通信印鉴
jnz short old_vect ;否,转数据采集
cmp bx, 0 ;申请类别鉴定
jnz short check
mov bx, ax ;设置检查成功标志
jmp short return
check: cmp bx, 1 ;申请类别鉴定
jnz short old_vect ;否,转数据采集
mov ds, cx
mov bx, dx ;内存地址定位
; ...
;用户编制的数据处理过程
; ...
jmp short return
old_vect: ;数据采集,中断寄存器设置,判断是否有接受消息的窗口
return: [pop ......] ;恢复现场
iret
handle endp
ALIGN 16
init_resident:
dosdrv proc far
[ ...... ] ;中断向量地址的保存、设置,以及程序驻留
dosdrv endp
_TEXT ends
end dosdrv
Ⅱ.WINCOMM.CPP:
DWORD FAR PASCAL GlobalDosAlloc (DWORD);
UINT FAR PASCAL GlobalDosFree (UINT);
void IsTSR (void);
void CallTSR (void);
#include "windows.h"
#define WM_DOSWINCOMM WM_USER+1
int TestTSR = 0;
WORD PMSelector=0, SegAddr;
WORD FAR *farPtr;
DWORD windowsFlag;
long CALLBACK __export MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd; UINT message; WPARAM wParam; LPARAM lParam;
{ DWORD memoryPtr; /*Windows进程消息处理*/
switch (message)
{ case WM_CREATE: /*用户数据初始化过程*/
windowsFlag = GetWinFlags();
case WM_DOSWINCOMM:
if (! (windowsFlag & WF_PMODE))
{ /*Windows处于实模式的处理过程*/ break; }
IsTSR();
if (0==TestTSR)
{ /*DOS Driver未安装处理过程*/ }
else
if (0==PMSelector)
{ /*申请内存失败的处理*/ }
else
{ /*用户可根据需要申请内存*/
memoryPtr = GlobalDosAlloc(2);
PMSelector = LOWORD (memoryPtr);
SegAddr = HIWORD (memoryPtr);
farPtr = (WORD FAR *) ( (DWORD)PMSelector << 16);
CallTSR();
/*用户编制的处理过程*/
if (0!=PMSelector)
PMSelector = GlobalDosFree (PMSelector);
break; }
case WM_DESTROY:
if (0!=PMSelector)
PMSelector = GlobalDosFree (PMSelector);
PostQuitMessage(0);
break;
default: return (DefWindowProc(hWnd, message, wParam, lParam)); }
return (NULL);
}
下面的程序段为保护模式与实模式的接口:
void IsTSR()
{ _asm{ mov ax, 0200h
mov bl, 77h
int 31h ; DPMI调用
or cx, dx
jz short notsr
mov ax, 1234h
mov bx, 0
int 77h
;鉴别通信印鉴
cmp bx, 1234h
jnz short notsr
mov TestTSR, -1
notsr: }
}
void CallTSR()
{ _asm{ mov ax, 1234h
mov bx, 1
mov cx, SegAddr
xor dx, dx
int 77h }
}
所谓DPMI,是由Microsoft、Intel、IBM等多家公司联合建立的一种约定, 它规
定了一组服务程序,并可以在保护模式下使用INT 31h来调用它们。这些服务程序 的
提供者(如Windows 3.1)被称为DPMI服务程序(Server);而这些服务程序的使用者
(如保护模式下的DOS扩展程序)被称为客户程序(Client)。在同一个程序里,当需 要
由保护模式访问实模式的驱动程序或者TSR程序时,除了DPMI之外,别无选择。
在DOS提示符下运行DOSDRV.EXE程序,从而完成将被WINCOMM.EXE
调用的设备驱动
程序的安装。一旦Windows 被加载,即可运行WINCOMM.EXE程序以实现通信。
结束语
利用Windows内核函数GlobalDosAlloc()所获得的内存对于Windows虚拟机来 说
是局部的,因此其它的虚拟机不能够访问该段内存。这种方法作为DOS设备驱动程 序
与Windows应用程序之间进行通信的一种模式,如经稍加改进,可以实现多个
Windows进程共同拥有一个DOS设备驱动程序,而相互之间互不干扰。当然也可以 实
现Windows进程之间的通信。
-- 小白小白。一洗就白
表白表白。一清二白。。。。。。。。。
你忠实的朋友!!!!!
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.34.196]
|
|