- 浏览: 970723 次
- 性别:
- 来自: 珠海
文章分类
最新评论
-
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 9310Filter驱动可以实现简单的防火墙功能。它可以过滤所有接收到 ... -
Ndis过滤驱动:拷贝NetBufferList数据
2010-04-19 22:40 9556今天我们来看看如何拷贝NBL中的数据。有时候需要更改数据包中的 ... -
在Filter驱动内核中获取IP地址
2010-04-18 01:48 3892项目开发中有时候需要在Filter驱动中获取有效地Unic ... -
如何在内核中获得当前系统时间
2010-04-16 15:08 2717在 Windows NT 内核中你是无法使用 tim ... -
Filter发送自定义数据详解
2010-04-16 10:30 5756... -
DebugPrint 格式说明符
2010-04-13 19:46 17631) 直接打印字符串。 DbgPrint(“Hello ... -
WDK+Visual Studio 2008配置编译驱动
2010-04-12 23:36 5561Introduction As it is known, ... -
疑问:关于内存释放
2010-04-12 21:33 1452今天碰到一个比较棘手的内存处理问题。 首先来看一个数据结构: ... -
Windows NT 驱动程序开发人员提示 -- 应注意避免的事项
2010-04-10 11:32 2321原讨论链接: http://community.cs ... -
关于DeviceIoControl实现异步的笔记【1】
2010-04-08 22:26 11742一直所做的都是同步实现的。当然很多情况这并不是很好的解决问题。 ... -
驱动和应用层的异步通信
2010-04-08 20:55 5405作 者: sislcb时 间: 2008-01-28,11:1 ... -
Windows系统编程之异步I/O和完成端口
2010-04-08 19:40 2316一、 同步I/O和异步I/O ... -
纵横捭阖C++之从异步谈起
2010-04-08 19:31 3216一般来说,简单的异步(Asynchronous)调用是这样一种 ... -
使用DeviceIoControl通信
2010-04-04 22:53 7902在很多时候,某些用户需要与底层驱动有一个交互式的操作,所 ... -
在驱动中使用链表
2010-04-03 14:06 3289文章作者:grayfox 作 ... -
疑问:数据包Length增大的原因
2010-04-01 14:35 1365现象: 自己定义一个仅含有Ethernet Header的数 ... -
疑问:为何无线网卡无法发送数据?
2010-03-30 22:42 4562所有的测试流程表明,程序已经成功的创建新的数据包,然后调用Nd ... -
InsertHeadList和CONTAINING_RECORD
2010-03-29 16:36 3753LIST_ENTRY定义一个双向链表的数据结构: typed ... -
如何区分不同的Filter Module Instance
2010-03-29 14:50 1537前文 说到如何区分不同Filter Module Inst ... -
大数据是否需要封装在多个MDL中发送
2010-03-27 21:40 2516前段时间,我们已经解决如何发送自定义的网络数据。那么接下来要做 ...
相关推荐
例如,对于可能耗时的操作,驱动可能需要将`DeviceIoControl`转换为异步处理,使用IRP的挂起和完成机制。同时,为了防止内存泄漏,驱动必须正确地释放分配的资源,而应用程序也需要处理可能的错误状态。 总的来说,...
在Windows系统中,DeviceIoControl函数是驱动程序开发者常用的接口,用于发送控制代码到设备对象,实现对硬件设备的特殊操作。本文将深入探讨DeviceIoControl的相关知识点,并结合Aida整理的实战案例进行解析。 一...
`DeviceIoControl`是Windows平台下实现设备驱动交互的关键接口之一。通过对该函数的深入理解和合理利用,开发者可以更加灵活地控制和管理各种硬件资源,提高软件的性能和稳定性。在实际开发过程中,还需要注意对错误...
综上所述,`DeviceIoControl`函数是Windows系统中与设备交互的重要工具,开发者可以通过它实现对设备的精细控制,实现更复杂的功能。在实际开发中,需要充分理解控制代码的含义,合理使用缓冲区,并注意错误处理和...
总之,DeviceIoControl是Windows系统中驱动程序与应用程序间的关键桥梁,通过它,我们可以实现对硬件设备的精细控制。在pdiusbd12这样的USB驱动中,熟练掌握DeviceIoControl的使用技巧,能够帮助开发者高效地进行...
本实战教程将深入探讨如何使用DeviceIoControl来直接操控设备,从而实现对硬件的高级控制。以下是对这个主题的详细阐述: DeviceIoControl是Windows系统内核提供的一个系统调用,它允许用户模式的应用程序向设备...
总的来说,DeviceIoControl是Windows系统中实现设备控制的关键工具,通过它,开发者可以直接与硬件对话,实现设备的个性化操作。理解和掌握DeviceIoControl的使用,对于进行系统级编程和设备驱动开发至关重要。
在实现异步完成时,驱动程序通常会执行以下步骤: - **注册I/O完成例程**:当驱动程序接收到I/O请求时,它会为该请求分配一个I/O完成上下文,并在设备队列上设置一个I/O完成例程。这样,当I/O操作完成时,系统会...
- **实现方式各异**:DeviceIoControl的实现涉及到应用程序与驱动程序之间的通信链路,而KernelIoControl则是通过驱动程序与内核层之间的接口实现的。 - **编程难度差异**:通常来说,DeviceIoControl相对易于理解和...
在设备驱动程序设计中,DeviceIOControl是一个强大的工具,它可以用来实现诸如读写扇区、查询设备状态、配置设备参数等复杂功能。但需要注意的是,不正确的使用可能会导致系统不稳定,因此在编写和使用时必须谨慎。 ...
6. **实例分析**:书中可能涵盖了一些实际的DeviceIoControl应用案例,如读写硬盘扇区、获取硬件配置信息、控制网络适配器等,这些都是通过DeviceIoControl实现的典型操作。 7. **调试技巧**:学习如何使用调试工具...
易语言DeviceIoControl取硬盘序列号源码,DeviceIoControl取硬盘序列号,倒序排列,DeviceIoControl,CreateFileA,CloseHandle,GetLastError,LocalAlloc,LocalFree
在驱动开发领域,`DeviceIoControl`函数是一个非常重要的API,它主要用于实现用户模式应用程序与内核模式驱动程序之间的通信。通过这个函数,用户空间的应用程序可以向驱动程序发送控制代码,并接收相应的数据。下面...
最后,压缩包中的"opencadr"可能是源代码文件或者相关文档,通过查看这些内容,你可以得到更具体的实现细节和步骤,从而加深对`DeviceIoControl`和`CreateFile`使用的理解。在实际开发中,遵循良好的编程实践,如...
本文将深入探讨`passthru`技术,以及如何利用`DeviceIoControl`函数来实现这种交互,同时关注`NDIS`(网络驱动接口规范)的相关知识。 `passthru`技术的核心在于允许应用程序直接对硬件设备发送原始I/O请求,而不是...
DeviceIoControl取硬盘序列号.rar
关于DeviceIoControl实现异步的笔记【2】 - **笔记内容**:进一步深入探讨DeviceIoControl实现异步通信的关键技术和最佳实践。 - **学习价值**:通过实际案例加深对异步通信的理解。 #### 42. Windows NT驱动程序...
DeviceIoControl() CreateFile() 读取硬件物理网卡mac完整工程实例 Vs2012 c++ 源代码 功能:结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址 入口参数: iQueryType:需要获取的... -2:WMI连接失败