应用层与驱动层同步事件处理方法

源地址:http://hi.baidu.com/zkriymfvqfbaglq/item/90207f0785d2b713cd34ea53不保证一定是最初的博文地址

关于这个问题高手略过吧。

Ring3与Ring0同步是很有用的手段,在此做一个简要的整理,希望对开发这方面程序的朋友有帮助,好了,开始吧。

1 同步的策略

初写驱动的朋友都知道,通过DeviceIoControl这个API函数, 可以将Ring3的数据及控制请求发送给Ring0.但这是单向的,由Ring3主动发起,Ring0被动接受。可以说这是单向轮询的。

                                              询问(CTL_CODE)

Ring3     ---------------------------------------------------------------- >     Ring0  

                                              回答(通过OUT参数)

Ring3     <----------------------------------------------------------------       Ring0  

这种方式用于主动获取Ring0数据,又不要求效率,和具有实时性的开发情况。

但做监控类软件却与此相反,是Ring0先监控到事件,具有主动权,发起询问通知Ring3。

                                           监控到事件(通知)

Ring0(监控)----------------------------------------------------------------> Ring3  

在实时性要求不高的情况下可以采用Ring3定时询问Ring0,当然Ring0保存了事件的状态。

这里介绍的就是高实时性,大数据传输的同步解决办法。

原理:通过Ring3创建事件,并将该事件传递给Ring0,同时Ring3创建监控线程,等待Ring0发起事件,此为应用层驱动层共享事件。同时Ring0在内核分配非分页内存,通过DeviceIoControl 传递给Ring3,此为应用层驱动层共享内存。因在DeviceIoControl 中传送Buffer,涉及到内核数据拷贝,大数据量下使用效率很低,故用共享内存的方法。

2 具体实现

Ring3:

// 创建事件
HANDLE m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);

// 发事件给ring 0
if (0 == DeviceIoControl(	hFile, \    
							SET_EVENT, \                                      
							&m_hEvent, \
							sizeof(HANDLE), \
							NULL, \
							0,\
							&uRetBytes,
							NULL)) 
{
	CloseHandle(hFile);
	CloseHandle(m_hEvent); 
	return ;
}

// 获得ring 0 的共享内存
unsigned int add = 0;
if (0 == DeviceIoControl(	hFile, \                 
							GET_SHARE_ADD, \
							NULL, \
							0, \
							&add, \
							sizeof (unsigned int),\
							&uRetBytes,
							NULL)) 
{
	CloseHandle(hFile);
	CloseHandle(m_hEvent); 
	return ;
} 
m_pShareMem =(PVOID)add;                            
//映射的共享内存
//当Ring0有事件产生时,Ring3的线程就可处理m_pShareMen了。
UINT WorkThread(PVOID param)
{              
	...............
	while(!bExit)
	{
				 WaitForSingleObject(g_hEvent,INFINITE);   
				 ......................
				 // 可以处理分析m_pShareMen 了
	}
}

Ring0:

PVOID g_pSysAdd = NULL; 
PMDL  g_pMdl    = NULL;      // 与ring 3 的共享内存描述
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
	......
	g_pSysAdd = ExAllocatePool(NonPagedPool, SHARE_MLEN + IPHEDLEN);
	g_pMdl = IoAllocateMdl(g_pSysAdd, SHARE_MLEN + IPHEDLEN, FALSE, FALSE, NULL);
	MmBuildMdlForNonPagedPool(g_pMdl);                    
	......
}

// I/O控制派遣例程
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

// 取得I/O控制代码
	ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	switch(uIoControlCode)
	{
		case SET_EVENT:     // 处理Ring3的事件
			if(g_pInBuffer == NULL||g_nInBuffSize < sizeof(HANDLE))
			{
				status = STATUS_INVALID_BUFFER_SIZE;
				break;
			}
			
			hEvent = *(HANDLE *)g_pInBuffer;
			status = ObReferenceObjectByHandle(	hEvent,
												SYNCHRONIZE,
												*ExEventObjectType,
												KernelMode,
												(PVOID *)&g_pEvent,
												&objHandleInfo
												);
			if(!NT_SUCCESS(status))
			{
				g_pEvent = NULL;
			}
			
			DbgPrint("g_pEvent: %x\n",g_pEvent);       // 得到了ring 3 事件句柄
			break;

		case GET_SHARE_ADD:                           //     传给ring 3 内存地址
			UserAddr = MmMapLockedPages(g_pMdl, UserMode);
			*((PVOID *)(pIrp->AssociatedIrp.SystemBuffer)) = UserAddr;
			status = STATUS_SUCCESS;   
			break;  
	}
	..............
}

RtlCopyMemory(g_pSysAdd,pSource,dwLen)               	//     将写数据到共享内存,
KeSetEvent((PKEVENT)g_pEvent,0,false);                  //      此刻Ring3就可以接受数据了。

//最后一步记得释放内存。
void DriverUnload(PDRIVER_OBJECT pDriverObj)
{ 
	// 清除共享内存

	IoFreeMdl(g_pMdl);
	ExFreePool(g_pSysAdd);

	// 删除设备对象
	IoDeleteDevice(pDriverObj->DeviceObject);
}

以上就是整个处理过程。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值