- 浏览: 958160 次
- 性别:
- 来自: 珠海
文章分类
最新评论
-
Yunjey:
Yunjey 写道这样子的话、grid中的editable如何 ...
Flex创建可编辑以及分页的DataGrid -
Yunjey:
这样子的话、grid中的editable如何设置啊?!
Flex创建可编辑以及分页的DataGrid -
di1984HIT:
写的很好~~
JCalendar组件 -
sanny81:
此文真棒!感谢一路风尘的奉献!
但我有一疑 ...
Filter发送自定义数据详解 -
umgsai:
求完整demo umgsai@126.com
Flex和Jsp创建用户登入系统
前面我们谈到了关于异步I/O的实现:关于DeviceIoControl实 现异步的笔记【1】 。可是实现起来,你会发现你的程序在DevieIoControl已经被挂起,而且返回的结果是非0。这就与真正的异步调用返回结果有出入,理论上应该返回0,且GetLastError()值为ERROR_IO_PENDING。
/** Send the packets defined by users */ BOOL FilterWrapper::SendMyOwnPacket() { BOOL result = FALSE; DWORD bytesWritten = 0; DWORD varEventResult; OVERLAPPED varOverLapped; HANDLE varObjectHandle = 0; LPVOID testBuffer = NULL; PBYTE pBuf = NULL; DWORD testBufferLength = (DWORD)sizeof("Hi Mon, I finish your request!\n"); testBuffer = new BYTE[testBufferLength]; if(testBuffer == NULL) { goto Exit; } varObjectHandle = CreateEvent(NULL,TRUE, TRUE,""); if(varObjectHandle == NULL) goto Exit; memset(&varOverLapped,0,sizeof(OVERLAPPED)); varOverLapped.hEvent = varObjectHandle; varOverLapped.Offset = 0; varOverLapped.OffsetHigh = 0; // pass a new io control to underlying driver to send packets if(!DeviceIoControl( m_hFilter, IOCTL_FILTER_SEND_MYOWN_PACKET, "Request from user mode to Send A Packet.\n", sizeof("Request from user mode to Send A Packet.\n"), testBuffer, testBufferLength, &bytesWritten, (LPOVERLAPPED)&varOverLapped)) { //printf("Can't Send Packet\n"); if(GetLastError() != ERROR_IO_PENDING) { printf("Overlapped I/O exception\n"); goto Exit; }else{ printf("Overlappedn pending....\n"); } } printf("Son, I am calling you for dinner...\n"); varEventResult = WaitForSingleObject(varObjectHandle,6000); switch(varEventResult) { case WAIT_OBJECT_0 : printf("overlapped i/0 workss\n"); pBuf = (PBYTE)testBuffer; printf("Return buffer is %s\n",pBuf); result = TRUE; break; case WAIT_TIMEOUT: varEventResult = CancelIo(m_hFilter); result = FALSE; break; default: break; } // printf("Successfully Send A packet!^_^\n"); ResetEvent(varObjectHandle); CloseHandle(varObjectHandle); Exit: delete[] testBuffer; return result; }
所以每次都不会打印Overlappedn pending....这一句,因为DeviceIoControl返回为非零。我原本愚蠢的以为,底层驱动是不需要更改就可以实现异步I/O。但是我错了,从一开始我就错了。那么亡羊补牢吧。我们进行底层驱动的处理:
由于你要求驱动做的工作不能即时完成,所以我们先返回一个PENDING状态:
case IOCTL_FILTER_SEND_MYOWN_PACKET: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; //这里等下讲如何叫底层驱动做该做的事情 //一个疑问在这里:如果像常规的函数在这里调用,那么跟同步I/O有何差异? //如果不这样,有其他方法吗? DEBUGP(DL_TEST,("I am waiting this io dispath\n")); Status = STATUS_PENDING; IoMarkIrpPending(Irp); Irp->IoStatus.Status = Status; return Status; break;
这里返回的状态为STATUS_PENDING,所以导致GetLastError值为ERROR_IO_PENDING,而是用overlapped i/o的异步方式导致DeviceIoControl返回为0.
别以为要做好了,还有好多疑问:
- 如何叫底层驱动做我么要他做的事情呢(很明显这里不能用常规的函数,否则当前线程就会执行这个函数的功能)
- 刚才的IRP请求到底执行结束没?
- 最后以何种方式告诉User层应用程序,某个时间已经是signaled状态,然后读取最后执行结果?
带着这个三个问题,我们继续讲:
既然不能用常规的函数,我们想想有什么方法可以让这个函数独立运行,而不受当前线程控制,答案就是在创建一个线程,负责该项工作。所以在上面的代码中间添加:
Status = PsCreateSystemThread(&threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE) printSomething, Irp ); if( !NT_SUCCESS(Status)) { DEBUGP(DL_TEST,("Fail to start a thread!\n")); return Status; }
注意这里传入当前IRP的指针。当该线程完成工作后,结束该IRP。
接下来看看线程调用printSomething这个函数:
VOID printSomething( IN PIRP pIrp ){ PUCHAR OutputBuffer = NULL; PUCHAR pTestBuf = "Hi Mon, I finish your request!\n"; ULONG bufSize = sizeof("Hi Mon, I finish your request!\n"); mySleepTimer(5); DEBUGP(DL_TEST,("Five seconds,I have finished done something,hahhaha\n")); pIrp->IoStatus.Status = NDIS_STATUS_SUCCESS; OutputBuffer = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer; NdisMoveMemory(OutputBuffer,pTestBuf,bufSize); pIrp->IoStatus.Information = bufSize; IoCompleteRequest(pIrp, IO_NO_INCREMENT); PsTerminateSystemThread(STATUS_SUCCESS); }
这里,我们等待5秒钟,然后返回。返回前设置输出缓冲区的数据,返回给user,其次设置返回的状态Success等。最后调用IoCompleteRequest()函数通知User中的Event事件,把Event设置成Signaled状态,使得WaitForSignalObject函数可以继续执行。
这样才完成异步I/O的调用,其实自己细看,使用同步时,DeviceIoControl被挂起,现在使用异步,DeviceIoControl立刻返回,但是在WaitForSignalObject中挂起等待Event的状态改变。所以要真正实现异步,估计还需要在User层使用线程,用线程负责该DeviceIoControl的调用。才能真正意义上实现异步。
----------------------------------------附上MySleepTimer()------------------------------
这个函数实现的功能是延迟5秒钟。
VOID mySleepTimer( IN ULONG time ){ LARGE_INTEGER my_interval; my_interval.QuadPart = RELATIVE(SECONDS(5)); KeDelayExecutionThread(KernelMode,FALSE,&my_interval); }
关键是在SECONDS()的宏定义,来自Osronline的牛人写的:
//Define some times #define ABSOLUTE(wait) (wait) #define RELATIVE(wait) (-(wait)) #define NANOSECONDS(nanos) \ (((signed __int64)(nanos)) / 100L) #define MICROSECONDS(micros) \ (((signed __int64)(micros)) * NANOSECONDS(1000L)) #define MILLISECONDS(milli) \ (((signed __int64)(milli)) * MICROSECONDS(1000L)) #define SECONDS(seconds) \ (((signed __int64)(seconds)) * MILLISECONDS(1000L))
所以等相对的5秒钟就是 RELATIVE(SECONDS(5)),很强大~
------------------------------------附上图片---------------------------------
执行过程中,WaitForsignalObject被挂起:
最后执行完成:
下面是Debugview信息:
0005056 261.43447876 NDISLWF:
00005057 261.43450928 The input length is 42, and inputdata is Request from user mode to Send A Packet.
00005058 261.43450928
00005059 261.43460083 NDISLWF:
00005060 261.43460083 I am waiting this io dispath
.......
00005229 266.43710327 NDISLWF:
00005230 266.43713379 Five seconds,I have finished done something,hahhaha
-------------------参考资料-----------------
- DPC定时器何时返回的问题 http://bbs.pediy.com/showthread.php?t=110344
- 内核中线程的创建与销毁 http://hi.baidu.com/sysinternal/blog/item/f2b877084535c532e92488cc.html
- 关于DeviceIoControl异步调用的笔记【1】:http://yexin218.iteye.com/blog/638445
最后感谢两个人: 南部天天以及古越魂
评论
members of OVERLAPPED structure to zero before calling DeviceIoControl.
But what are you doing in the device driver? Here is an excerpt from the
MSDN KB article Q117308 (their site seems to be down, otherwise I would
direct you to the page).
"The driver should not complete the I/O request until an event has occurred.
When the driver receives the I/O request, if an event has occurred and is
waiting to be sent to the application, the driver can complete the request
in the dispatch routine. If no event is waiting to be reported, the driver
should perform the following steps:
1. Mark the Irp pending, using IoMarkIrpPending().
2. Set up a cancel routine for the Irp, using IoSetCancelRoutine().
3. Put the Irp in a storing place (a queue for example).
4. Return STATUS_PENDING from the dispatch routine.
Later, when an event has occurred, the driver can complete the pending
request from its deferred procedure call (DPC) routine. Before the Irp can
be completed, the driver should set the cancel routine address to NULL
using IoSetCancelRoutine."
发表评论
-
Filter驱动:过滤(修改)接受数据包
2010-04-20 16:18 9215Filter驱动可以实现简单的防火墙功能。它可以过滤所有接收到 ... -
Ndis过滤驱动:拷贝NetBufferList数据
2010-04-19 22:40 9451今天我们来看看如何拷贝NBL中的数据。有时候需要更改数据包中的 ... -
在Filter驱动内核中获取IP地址
2010-04-18 01:48 3845项目开发中有时候需要在Filter驱动中获取有效地Unic ... -
如何在内核中获得当前系统时间
2010-04-16 15:08 2660在 Windows NT 内核中你是无法使用 tim ... -
Filter发送自定义数据详解
2010-04-16 10:30 5684... -
DebugPrint 格式说明符
2010-04-13 19:46 17241) 直接打印字符串。 DbgPrint(“Hello ... -
WDK+Visual Studio 2008配置编译驱动
2010-04-12 23:36 5519Introduction As it is known, ... -
疑问:关于内存释放
2010-04-12 21:33 1408今天碰到一个比较棘手的内存处理问题。 首先来看一个数据结构: ... -
Windows NT 驱动程序开发人员提示 -- 应注意避免的事项
2010-04-10 11:32 2284原讨论链接: http://community.cs ... -
关于DeviceIoControl实现异步的笔记【1】
2010-04-08 22:26 11635一直所做的都是同步实现的。当然很多情况这并不是很好的解决问题。 ... -
驱动和应用层的异步通信
2010-04-08 20:55 5338作 者: sislcb时 间: 2008-01-28,11:1 ... -
Windows系统编程之异步I/O和完成端口
2010-04-08 19:40 2222一、 同步I/O和异步I/O ... -
纵横捭阖C++之从异步谈起
2010-04-08 19:31 3138一般来说,简单的异步(Asynchronous)调用是这样一种 ... -
使用DeviceIoControl通信
2010-04-04 22:53 7844在很多时候,某些用户需要与底层驱动有一个交互式的操作,所 ... -
在驱动中使用链表
2010-04-03 14:06 3238文章作者:grayfox 作 ... -
疑问:数据包Length增大的原因
2010-04-01 14:35 1326现象: 自己定义一个仅含有Ethernet Header的数 ... -
疑问:为何无线网卡无法发送数据?
2010-03-30 22:42 4481所有的测试流程表明,程序已经成功的创建新的数据包,然后调用Nd ... -
InsertHeadList和CONTAINING_RECORD
2010-03-29 16:36 3718LIST_ENTRY定义一个双向链表的数据结构: typed ... -
如何区分不同的Filter Module Instance
2010-03-29 14:50 1504前文 说到如何区分不同Filter Module Inst ... -
大数据是否需要封装在多个MDL中发送
2010-03-27 21:40 2463前段时间,我们已经解决如何发送自定义的网络数据。那么接下来要做 ...
相关推荐
DeviceIoControl的技术应用,我刚从网上下来的,非常好的语言
驱动程序函数DEVICEIOCONTROL的详细说明
硬件设备读写的基本操作DeviceIoControl,入门级教程
易语言DeviceIoControl取硬盘序列号源码,DeviceIoControl取硬盘序列号,倒序排列,DeviceIoControl,CreateFileA,CloseHandle,GetLastError,LocalAlloc,LocalFree
DeviceIoControl取硬盘序列号.rar
DeviceIOControl实战演示及源代码,是应用程序与设备通信很好的示例教程
硬件读写操作函数DeviceIoControl具体说明和用法,含样例代码
实战DeviceIoControl。 Aida整理。希望与大家多交流驱动开发经验。
DeviceIoControl CreateFile DeviceIoControl读取无线网卡mac完整工程实例 方便大家学习,如果还是看不懂,可以给我发邮件,帮你们解决
简单讲述了下KernelIoControl和DeviceIoControl的区别,及其使用方法
一个WDM驱动,然后caller使用DeviceIoControl进行和驱动的通信。输出buffer使用METHOD_IN_DIRECT进行数据传输。
实战DeviceIoControl:通过API访问设备驱动程序
DeviceIoControl() CreateFile() 读取硬件物理网卡mac完整工程实例 Vs2012 c++ 源代码 功能:结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址 入口参数: iQueryType:需要获取的... -2:WMI连接失败
驱动开发:DeviceIoControl函数的详细使用说明,附加实例
网上有很多版本的《实战DeviceIoControl》,我这里做了一下整理,希望能对大家有所帮助。
实战DeviceIoControl:通过API访问设备驱动程序
VC++在使用DeviceIoControl函数时可以直接使用控制码的代号,VB(或者其它语言)就没这么方便了。本程序可以根据控制码的代号得到控制码的16进制值。