`
yexin218
  • 浏览: 970741 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

关于DeviceIoControl实现异步的笔记【1】

阅读更多

一直所做的都是同步实现的。当然很多情况这并不是很好的解决问题。现在手上的问题是:用户层通知底层驱动(Filter Driver)做某件事,然后返回该事件执行的结果。如果该事件是一件简单的事情,这里是指极短时间内可以完成的,那么在允许范围内,我们可以用同步来完成。但是如果该事件是一件耗时的工作,而应用程序不能一直在等着该事件的完成信号,况且好像DeviceIoControl有时间限制的(?)。这就需要用异步的方式来解决问题:例如:同事叫你去吃饭,你听到后,可以马上去,也可以等会再去,吃完后再回到Office就好了。关键是我以前没有实现过,现在就手上的数资料来分析下可以实现的流程。

一、我们先看看关键函数DeviceIoControl:

BOOL WINAPI DeviceIoControl(
  __in         HANDLE hDevice,
  __in         DWORD dwIoControlCode,
  __in_opt     LPVOID lpInBuffer,
  __in         DWORD nInBufferSize,
  __out_opt    LPVOID lpOutBuffer,
  __in         DWORD nOutBufferSize,
  __out_opt    LPDWORD lpBytesReturned,
  __inout_opt  LPOVERLAPPED lpOverlapped
);

+ ===== lpOverlapped ===== 
+ 一个指向OVERLAPPED结构体的指针
+ 如果hDevice用FILE_FLAG_OVERLAPPED 形式打开,lpOverlapped 必须指向一个合法的OVERLAPPED结构体。在这种情况下,进行异步操作
+ 如果hDevice用FILE_FLAG_OVERLAPPED 形式打开,而lpOverlapped为NULL,函数会返回不可预知的错误。
+ 如果hDevice打开时没有指定FILE_FLAG_OVERLAPPED 标志,lpOverlapped参数将被忽略,进行同步操作,函数直到操作完成或出现错误时才返回。

所以这里我们必须首先以FILE_FLAG_OVERLAPPED打开设备驱动。这里我们需要在CreateFile中指定:

HANDLE WINAPI CreateFile(
  __in      LPCTSTR lpFileName,
  __in      DWORD dwDesiredAccess,
  __in      DWORD dwShareMode,
  __in_opt  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  __in      DWORD dwCreationDisposition,
  __in      DWORD dwFlagsAndAttributes,
  __in_opt  HANDLE hTemplateFile
);

 如果dwFlagsAndAttributes指定值为:FILE_FLAG_OVERLAPPED,那么

写道
The file or device is being opened or created for asynchronous I/O.

When subsequent I/O operations are completed on this handle, the event specified in the OVERLAPPED structure will be set to the signaled state.

If this flag is specified, the file can be used for simultaneous read and write operations.

If this flag is not specified, then I/O operations are serialized, even if the calls to the read and write functions specify an OVERLAPPED structure.

For information about considerations when using a file handle created with this flag, see the Synchronous and Asynchronous I/O Handles section of this topic.

 

现在的问题来了,我们Overlapped的方式打开设备驱动,然后以异步的方式调用了DeviceIoControl,所以该函数会立马返回,返回值正确的应该为:ERROR_IO_PENDING 。这就表明底层驱动接受到了请求,然后应用程序应该有一种方式可以检测到该请求被底层正确执行完成的信号。

这里有个疑问:网上看到很多的例子,都是手动触发异步的完成,包括:驱动和应用层的异步通信

他们的做法没有等到最后的执行结果返回:所以在底层驱动手动设置了一些信息:

//获取irp状态
    pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = STATUS_SUCCESS;

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    IoCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
        switch (IoCode)
    {
    case IO_TEST_PENDING:
        status = PsCreateSystemThread(&hthread, (ACCESS_MASK)0L, NULL, (HANDLE)0, NULL, ThreadPending, NULL);
        if (!NT_SUCCESS(status))
        {
            return status;
        }
        
        KdPrint(("Pending thread ok..."));

    //直接设置为pending 返回给应用层。
        status = STATUS_PENDING;
        IoMarkIrpPending(pIrp);
        pIrp->IoStatus.Status = status;
        return status;
        break;    
    }

 

可能他们仅仅是为了测试,没有叫底层驱动做一些复杂的事情。接着讲...

二、等待执行完成信号

这里调用WaitForSingleObject并传递设备内核对象的句柄。

WaitForSingleObject会挂起调用线程直至内核对象变成有信号态。 

DWORD WINAPI WaitForSingleObject(
  __in  HANDLE hHandle,
  __in  DWORD dwMilliseconds
);

 

WaitForSingleObject 函数用来检测 hHandle 事件的信号状态,当函数的执行时间超过 dwMilliseconds 就返回,但如果参数 dwMilliseconds INFINITE 时函数将直到相应时间事件变成有信号状态才返回,否则就一直等待下去,直到 WaitForSingleObject 有返回直才执行后面的代码。

这里我们把它处理成一个Event,所以在调用DeviceIoControl之前,我们必须创建一个Event:

 

HANDLE CreateEvent(   
  LPSECURITY_ATTRIBUTES lpEventAttributes,   // 安全属性   
  BOOL bManualReset,   // 复位方式   
  BOOL bInitialState,   // 初始状态   
  LPCTSTR lpName   // 对象名称   
);  

 示例:  // 创建一个有名的,不能被继承的,手动复原,初始状态是无信号状态的事件对象
          Handle h = CreateEvent(NULL,TRUE,FALSE,“MyEvent”);  

然后作为OVERLAPPED数据成员传入DeviceIoControl函数。

例如:

OVERLAPPED varHIDOverlapped;
..
varEventObjectHandle = CreateEvent(NULL, TRUE, TRUE, "");

if(varEventObjectHandle == INVALID_HANDLE_VALUE || varEventObjectHandle
== NULL){

..}

varHIDOverlapped.hEvent = varEventObjectHandle;
varHIDOverlapped.Offset = 0;
varHIDOverlapped.OffsetHigh = 0;

varCommand[0] = 0x05;
varCommand[1] = 0;
varCommand[2] = 0;
DeviceIoControl (varUSBHandle, IOCTL_USBPRINT_VENDOR_GET_COMMAND,
varCommand, 3, varStatus, 31, (LPDWORD)&varNumberOfBytes, (LPOVERLAPPED)
&varHIDOverlapped);

varEventResult = WaitForSingleObject(varEventObjectHandle, 2000);

 

当varEventResult返回的结果是:WAIT_OBJECT_0。表明句柄是一个signaled状态,然后应用线程接着执行余下的代码:

switch (varEventResult)
{
case WAIT_OBJECT_0:
// It works
break;

case WAIT_TIMEOUT:
// Timeout
varEventResult = CancelIo(varUSBHandle);
break;

default:
break;
}

 

当然你也可是这样使用:

 // This will return immediately... 
ULONG rc = DeviceIoControl( handle_, IOCTL_TSII_BOARD_SIGNAL_AT_TIMECODE, &tcsp, 
sizeof(tcsp), NULL, NULL, &nbytes, &overlapped); // How do I handle this???
 if (rc == 0){ 
     if (GetLastError() != ERROR_IO_PENDING) { 
               throw Exception("overlapped i/o exception\n");
     
      }
    } 
DWORD  transf_byte;
 if(GetOverlappedResult(handle_,&overlapped,&transf_byte,TRUE) == 0)
{ //ERROR

}

 

关于GetOverlappedResult:

BOOL
WINAPI
GetOverlappedResult(
    HANDLE hFile,
    LPOVERLAPPED lpOverlapped,
    LPDWORD lpNumberOfBytesTransferred,
    BOOL bWait
    )

 

  The GetOverlappedResult function returns the result of the last
    operation that used lpOverlapped and returned ERROR_IO_PENDING.

这样应该就差不多可以了吧(我猜的~,细节除外)。

下面是参考资料:

  1. 驱动和应用层的异步通信 http://bbs.pediy.com/showthread.php?t=59015
  2. DeviceIoControl的异步问题http://bbs.driverdevelop.com/read.php?tid-67288.html
  3. WaitForSingleObject的用法http://hi.baidu.com/zouhaoo/blog/item/1e863851615e3b858d54306c.html
  4. 多线程中使用waitforsingleobject方法http://www.360doc.com/content/09/0428/12/27287_3299491.shtml
  5. DeviceIoControl return code using Overlapped I/O http://www.osronline.com/showthread.cfm?link=167510
  6. 应用层跟驱动异步通信的问题,irp该如何处理?http://bbs.driverdevelop.com/read.php?tid-113399.html
  7. DeviceIOControl and overlapped I/O problem http://forums.devshed.com/c-programming-42/deviceiocontrol-and-overlapped-i-o-problem-255708.html
  8. http://www.techtalkz.com/microsoft-device-drivers/295657-deviceiocontrol-overlapped.html
  9. DeviceIoControl and OVERLAPPED problem
0
0
分享到:
评论
1 楼 yexin218 2010-04-08  
今天先写到这里,明天写程序检测。。。。。。。。

相关推荐

    使用DeviceIoControl进行通信(直接方式)

    例如,对于可能耗时的操作,驱动可能需要将`DeviceIoControl`转换为异步处理,使用IRP的挂起和完成机制。同时,为了防止内存泄漏,驱动必须正确地释放分配的资源,而应用程序也需要处理可能的错误状态。 总的来说,...

    实战DeviceIoControl.rar

    在Windows系统中,DeviceIoControl函数是驱动程序开发者常用的接口,用于发送控制代码到设备对象,实现对硬件设备的特殊操作。本文将深入探讨DeviceIoControl的相关知识点,并结合Aida整理的实战案例进行解析。 一...

    DeviceIoControl解读

    `DeviceIoControl`是Windows平台下实现设备驱动交互的关键接口之一。通过对该函数的深入理解和合理利用,开发者可以更加灵活地控制和管理各种硬件资源,提高软件的性能和稳定性。在实际开发过程中,还需要注意对错误...

    DeviceIoControl

    综上所述,`DeviceIoControl`函数是Windows系统中与设备交互的重要工具,开发者可以通过它实现对设备的精细控制,实现更复杂的功能。在实际开发中,需要充分理解控制代码的含义,合理使用缓冲区,并注意错误处理和...

    实战DeviceIoControl.rar_deviceiocontrol_driver.IoControl_pdiusbd12

    总之,DeviceIoControl是Windows系统中驱动程序与应用程序间的关键桥梁,通过它,我们可以实现对硬件设备的精细控制。在pdiusbd12这样的USB驱动中,熟练掌握DeviceIoControl的使用技巧,能够帮助开发者高效地进行...

    实战DeviceIoControl:通过API访问设备驱动程序.rar

    1. DeviceIoControl的基本使用: - 调用格式:BOOL DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD ...

    DeviceIoControl详解及例程

    总的来说,DeviceIoControl是Windows系统中实现设备控制的关键工具,通过它,开发者可以直接与硬件对话,实现设备的个性化操作。理解和掌握DeviceIoControl的使用,对于进行系统级编程和设备驱动开发至关重要。

    windows wdm驱动的例子,采用异步完成的方式实现驱动程序和应用程序通信的程序

    在实现异步完成时,驱动程序通常会执行以下步骤: - **注册I/O完成例程**:当驱动程序接收到I/O请求时,它会为该请求分配一个I/O完成上下文,并在设备队列上设置一个I/O完成例程。这样,当I/O操作完成时,系统会...

    KernelIoControl和DeviceIoControl的区别

    - **实现方式各异**:DeviceIoControl的实现涉及到应用程序与驱动程序之间的通信链路,而KernelIoControl则是通过驱动程序与内核层之间的接口实现的。 - **编程难度差异**:通常来说,DeviceIoControl相对易于理解和...

    DeviceIOControl函数实战演示及源代码

    在设备驱动程序设计中,DeviceIOControl是一个强大的工具,它可以用来实现诸如读写扇区、查询设备状态、配置设备参数等复杂功能。但需要注意的是,不正确的使用可能会导致系统不稳定,因此在编写和使用时必须谨慎。 ...

    实战DeviceIoControl全集

    1. **DeviceIoControl的基本使用**:DeviceIoControl函数接收四个主要参数:设备句柄、控制代码、输入缓冲区(可选)和输出缓冲区(可选)。在调用此函数之前,需要确保已经正确打开了设备,并且拥有足够的权限。...

    易语言DeviceIoControl取硬盘序列号

    易语言DeviceIoControl取硬盘序列号源码,DeviceIoControl取硬盘序列号,倒序排列,DeviceIoControl,CreateFileA,CloseHandle,GetLastError,LocalAlloc,LocalFree

    实战DeviceIoControl

    在驱动开发领域,`DeviceIoControl`函数是一个非常重要的API,它主要用于实现用户模式应用程序与内核模式驱动程序之间的通信。通过这个函数,用户空间的应用程序可以向驱动程序发送控制代码,并接收相应的数据。下面...

    DeviceIoControl读取无线网卡mac完整工程实例

    最后,压缩包中的"opencadr"可能是源代码文件或者相关文档,通过查看这些内容,你可以得到更具体的实现细节和步骤,从而加深对`DeviceIoControl`和`CreateFile`使用的理解。在实际开发中,遵循良好的编程实践,如...

    passthru使用DeviceIoControl进行高层与底层的交互

    本文将深入探讨`passthru`技术,以及如何利用`DeviceIoControl`函数来实现这种交互,同时关注`NDIS`(网络驱动接口规范)的相关知识。 `passthru`技术的核心在于允许应用程序直接对硬件设备发送原始I/O请求,而不是...

    DeviceIoControl取硬盘序列号.rar

    DeviceIoControl取硬盘序列号.rar

    Filter驱动开发笔记

    关于DeviceIoControl实现异步的笔记【1】 - **笔记内容**:详细介绍如何使用DeviceIoControl实现异步通信的具体步骤和技巧。 - **实践意义**:有助于开发者更好地理解异步通信的实现机制。 #### 41. 关于...

    DeviceIoControl、CreateFile,结合WMI读取物理硬盘网卡mac特征码,完整源码工程实例

    DeviceIoControl() CreateFile() 读取硬件物理网卡mac完整工程实例 Vs2012 c++ 源代码 功能:结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址 入口参数: iQueryType:需要获取的网卡类型 0:包括...

Global site tag (gtag.js) - Google Analytics