中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Visual C++ > 系统
如何建立应用程序和驱动程序间的通信
作者:未知 时间:2005-07-20 14:20 出处:VC知识库 责编:chinaitpower
              摘要:如何建立应用程序和驱动程序间的通信

如何建立应用程序和驱动程序间的通信

作者:毛云祥

  驱动程序是为设备的硬件层编程服务的,但同样需要提供和应用程序进行通信的能力,从而最终达到应用程序控制设备的目的。本文主要讨论应用程序与驱动程序的通信和驱动程序与应用程序的通信。
  在Windows中,应用程序实现与WDM通信的过程是:应用程序先用CreateFile函数打开设备,然后用DeviceIoControl和WDM进行通信,包括从WDM读数据和写数据给WDM两种情况,也可用ReadFile从WDM中读数据或用WriteFile写数据给WDM。当应用程序退出时,用CloseHandle关闭设备。

以下是用DeviceIoControl写数据给WDM的源代码:

void Test_P9052_IOCTL_805_WriteBase3(void)
{
	ULONG	nOutput;						// Count written to bufOutput

	// 传给驱动程序要写入的参数和数据
	// 数组的第一个元素为写入的偏移地址,第二个元素为数据的个数,其它元素为写入的数据
	ULONG	bufInput[IOCTL_INBUF_SIZE+2];	
	ULONG   offset;       // 写入的偏移地址
	ULONG   num;          // 写入的初始数据,以此来产生一个数组
	
	printf("\n----------- ready for writing to Base3 -----------");
	
	//获取写入的偏移地址
	printf("\nPlease input the offset of the write operation(Hex):");
	scanf("%x",&offset);
//	//获取写入的数据个数
	bufInput[0]=offset;
	bufInput[1]=IOCTL_INBUF_SIZE;
	//获取写入的数据
	printf("\nPlease input the initial data to write(Hex):");
	scanf("%x",&num);
	for(ULONG j=0;j<IOCTL_INBUF_SIZE;j++)
	{
		bufInput[2+j]=num;
		num+=0x0;
	}
	//显示生成的数组
	for(ULONG i=0;i<IOCTL_INBUF_SIZE+2;i++)
	{
		printf("\nwrite data[%d]=%x",i,bufInput[i]);
	}
	// Call device IO Control interface in driver
	if (!DeviceIoControl(hDevice,
						 P9052_IOCTL_805_WriteBase3,
						 bufInput,
						 (IOCTL_INBUF_SIZE+2)*4,//sizeof(bufInput),
						 NULL,//bufOutput,
						 0,//sizeof(bufOutput),
						 &nOutput,
						 NULL)
	   )
	{
		printf("\nERROR: DeviceIoControl returns %0x.", GetLastError());
		Exit(1);
	}
	printf("\n\n");
}
以下是用DeviceIoControl从WDM中读数据的源代码:
void Test_P9052_IOCTL_804_ReadBase3(void)
{
	ULONG	bufOutput[IOCTL_OUTBUF_SIZE];	// 传出读取的数据缓冲区
	ULONG	nOutput;						// 实际读取的数据个数
        ULONG   bufInput[2];	 	            // 传入读取的参数
	ULONG   offset;                         // 要读取的偏移地址
	printf("\n----------- ready for reading from Base3 -----------");
	//获取读取的偏移地址:
	printf("\nPlease input the offset of read operation(Hex):");
	scanf("%x",&offset);
//	//获取读取的数据个数:
//	printf("\nPlease input the number of data to read(Dec):");
//	scanf("%d",&number);
	bufInput[0]=offset;
	bufInput[1]=IOCTL_OUTBUF_SIZE;
	// Call device IO Control interface (PCI9054_IOCTL_804_ReadBase3) in driver
	if (!DeviceIoControl(hDevice,
						 P9052_IOCTL_804_ReadBase3,
						 bufInput,
                         2*4,     // 字节
						 bufOutput,
						 IOCTL_OUTBUF_SIZE*4,//sizeof(bufOutput),
						 &nOutput,
						 NULL)
	   )
	{
		printf("\nERROR: DeviceIoControl returns %0x.", GetLastError());
		Exit(1);
	}
    printf("\n------>>>>>> data read <<<<<<------");
	for(ULONG i=0;i<nOutput;i++)
	{
		printf("\nread data[%d]=%x",i,bufOutput[i]);
	}
	printf("\n\n");
}

驱动程序与应用程序的通信:
与此相对应,当驱动程序捕捉到特点事件(如中断)发生时,应当可以与应用程序进行通信。 以下是通过I/O请求包(IRP),驱动程序的读数据函数:
VOID P9052Device::Serial_P9052_IOCTL_804_ReadBase3_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;
	t << "Entering P9052Device::Serial_P9052_IOCTL_804_ReadBase3_Handler, " << I << EOL;
	KMemory Mem(I.Mdl());     
	// Use the memory object to create a pointer to the caller''s buffer
	PULONG	pOutBuffer	= (PULONG) Mem.MapToSystemSpace();  //输出缓冲区指针,传出读取的数据
	PULONG  pInBuffer       = (PULONG) I.IoctlBuffer();     //输入缓冲区指针
	ULONG   Offset;                     //读取的偏移地址
	Offset   = *pInBuffer;
	ULONG   count;                      //读取的数据个数
	count    = *(pInBuffer+1);
	m_IoPortRange1_ForBase3.ind(Offset,pOutBuffer,count);
	I.Information() = count;
	I.Status() = status;
	m_DriverManagedQueue.PnpNextIrp(I);
}
以下是通过IRP,驱动程序的写数据函数:
VOID P9052Device::Serial_P9052_IOCTL_805_WriteBase3_Handler(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;
	t << "Entering P9052Device::Serial_P9052_IOCTL_805_WriteBase3_Handler, " << I << EOL;
	PULONG  pInBuffer  = (PULONG) I.IoctlBuffer(); //输入缓冲区指针
	ULONG   count;                        //从输入缓冲区要写入的数据个数
	count=*(pInBuffer+1);
	ULONG   offset;                       //偏移地址
	offset=*pInBuffer;
	PULONG  pBuffer  = pInBuffer+2;       //指向要写入的数据
	m_IoPortRange1_ForBase3.outd(offset,pBuffer,count);
	I.Information() = count;
	I.Status() = status;
	m_DriverManagedQueue.PnpNextIrp(I);
}
下图是运行时的界面:


图一 VC运行界面

  本文通过DriverWorks实现对PCI9052的数据写入、读出。读写方式是DirectIO方式。这是一种简单的方式,速度只能达到几M,如果是大批量的数据写入可以采用buffer的方式。
关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有