采用VXD技术实现实的通信
。Win32应用程序的呼叫会让VMM32送给该VXD一个系统信息,并传递进一个DIOCPARAMETERS结构的指针。该结构里包含Win32应用程序呼叫时传递进来的各个参数。这个结构的组成如下:
TypedefstunctDIOCParams{
DWORDInternall;//指向客户寄存器的指针
DWORDVMHande;//该VM的句柄
DWORDInternal2;//指向DDB结构的指针
DWORDdwIoConrolCode;//DeviceIoControl例程中呼叫的控制码
DWODlpvInBuffer;//DeviceIoControl例程呼叫所传递进来的输入缓冲区地址
DWORDcbInBuffer;//输入缓冲区的大小
DWORDlpvOutBuffer;//DeviceIoControl例程呼叫所传递进来的输出缓冲区地址
DWORDcbOutBuffer;//输出缓冲区的大小
DWORDlpcbBytesReturned;//拷贝到输出缓冲区中的字节数(可以为NULL)
DWORDlpOverlapped;//DeviceIoControl例程呼叫所传递进来的重叠I/O块结构
DWORDhDevice;//Ring3层呼叫应用程序句柄
DWORDtagProcess;//例程标签
}
DIOPARAMETERS;
其中,dwIoControlCode指明了Win32应用程序需要VXD提供的哪一项服务。在本例中采用一个switch-case语句作为服务入口,如下所示。其中服务1为让串口送出一个字节,服务2为读取一个已经由串口接收的字节。函数open_int()是用来初始化串口以便接收字节数据;函数BOOLserial_out(DWORDpBuffer)是让串口发出一个字节。它们的函数体分别如下:
BOOLserial_
out(DWORDpBuffer){
if(pBuffer==NULL){
returnFALSE;
}
_asm{
pushfd
cli
pusheax
pushedx
movdx,0x3fb;设置COM1的波特率
moval,0x83
outdx,al
movdx,0x3f8
moval,12
outdx,al
movdx,0x3f9
moval,0
outdx,al
movdx,0x3fb;设置COM1的线控项
moval,3
outdx,al
movdx,0x3f9;CMM1关中断
moval,0
outdx,al
movdx,0x3fa;关闭com1的FIFO功能
moval,0
outdx,al
movdx,0x3f8;字节发送
moval,byteptr[pBuffer]
outdx,al
popedx
popeax
popfd
sti
}
returnTRUE;
}
serial_out这个函数体的实现是用汇编语言实现的。因为涉及到很多的端口提供以及CPU的标志(flag)和压栈操作,因此考虑到用汇编语言编写会简化代码。因为此串口传输中,用到了关闭中断的指令(cli),所以,当写操作所要求完成的任务很多时,此关中断指令会让程序的实时性很好地体现出来,但cli指令有效时间过长会导致系统问题,所以还是要谨慎使用。
Voidopen_int(void){
_asm{
movdx,0x3f9;COM1开中断
moval,0x05
outdx,al
}
return;
}
open_int函数用来把PC串口的中断设备按照需要设立起来。函数体很简单,仅改变了地址为3F9h的内容,意为设置Rxdataready和Linestatus中断位,以便让CPU可以及时在COM1的中断服务程序里读取串口接收到的字节。
以上涉及到串口输入和输出的函数体实现代码中,用到了PC16550UART的资料。
至此,一个可用于实时串口通信的VXD驱动程序已经完成。由于篇幅所限,不能将其它必要的文档一同提出来讨论。
3Win32客户测试程序
有了上述VXD驱动程序,还需要搭配一个Win32客户程序来进行测试。在网络补充版中,给出一个笔者在VC6下编制的一个控制台应用程序片断,以供参考。
《采用VXD技术实现实的通信(第3页)》
本文链接地址:http://www.oyaya.net/fanwen/view/173349.html
TypedefstunctDIOCParams{
DWORDInternall;//指向客户寄存器的指针
DWORDVMHande;//该VM的句柄
DWORDInternal2;//指向DDB结构的指针
DWORDdwIoConrolCode;//DeviceIoControl例程中呼叫的控制码
DWODlpvInBuffer;//DeviceIoControl例程呼叫所传递进来的输入缓冲区地址
DWORDcbInBuffer;//输入缓冲区的大小
DWORDlpvOutBuffer;//DeviceIoControl例程呼叫所传递进来的输出缓冲区地址
DWORDcbOutBuffer;//输出缓冲区的大小
DWORDlpcbBytesReturned;//拷贝到输出缓冲区中的字节数(可以为NULL)
DWORDlpOverlapped;//DeviceIoControl例程呼叫所传递进来的重叠I/O块结构
DWORDhDevice;//Ring3层呼叫应用程序句柄
DWORDtagProcess;//例程标签
}
DIOPARAMETERS;
其中,dwIoControlCode指明了Win32应用程序需要VXD提供的哪一项服务。在本例中采用一个switch-case语句作为服务入口,如下所示。其中服务1为让串口送出一个字节,服务2为读取一个已经由串口接收的字节。函数open_int()是用来初始化串口以便接收字节数据;函数BOOLserial_out(DWORDpBuffer)是让串口发出一个字节。它们的函数体分别如下:
BOOLserial_
out(DWORDpBuffer){
if(pBuffer==NULL){
returnFALSE;
}
_asm{
pushfd
cli
pusheax
pushedx
movdx,0x3fb;设置COM1的波特率
moval,0x83
outdx,al
movdx,0x3f8
moval,12
outdx,al
movdx,0x3f9
moval,0
outdx,al
movdx,0x3fb;设置COM1的线控项
moval,3
outdx,al
movdx,0x3f9;CMM1关中断
moval,0
outdx,al
movdx,0x3fa;关闭com1的FIFO功能
moval,0
outdx,al
movdx,0x3f8;字节发送
moval,byteptr[pBuffer]
outdx,al
popedx
popeax
popfd
sti
}
returnTRUE;
}
serial_out这个函数体的实现是用汇编语言实现的。因为涉及到很多的端口提供以及CPU的标志(flag)和压栈操作,因此考虑到用汇编语言编写会简化代码。因为此串口传输中,用到了关闭中断的指令(cli),所以,当写操作所要求完成的任务很多时,此关中断指令会让程序的实时性很好地体现出来,但cli指令有效时间过长会导致系统问题,所以还是要谨慎使用。
Voidopen_int(void){
_asm{
movdx,0x3f9;COM1开中断
moval,0x05
outdx,al
}
return;
}
open_int函数用来把PC串口的中断设备按照需要设立起来。函数体很简单,仅改变了地址为3F9h的内容,意为设置Rxdataready和Linestatus中断位,以便让CPU可以及时在COM1的中断服务程序里读取串口接收到的字节。
以上涉及到串口输入和输出的函数体实现代码中,用到了PC16550UART的资料。
至此,一个可用于实时串口通信的VXD驱动程序已经完成。由于篇幅所限,不能将其它必要的文档一同提出来讨论。
3Win32客户测试程序
有了上述VXD驱动程序,还需要搭配一个Win32客户程序来进行测试。在网络补充版中,给出一个笔者在VC6下编制的一个控制台应用程序片断,以供参考。
《采用VXD技术实现实的通信(第3页)》