阅读:2323回复:8
关于DeviceIoControl异步的问题
关于DeviceIoControl异步的问题
我想用DeviceIoControl异步方式来向驱动来读取,目的是让它立即返回,但我调试的还是要等它完成了才返回 ,我是按相关例子在CreateFile( ) 和DeviceIoControl 中的参数都设置好了啊,是不是驱动中要改吗。要让它立即返回还要注意什么呢。 |
|
最新喜欢:![]() |
沙发#
发布于:2003-10-08 14:58
大侠们帮我看看吧
|
|
板凳#
发布于:2003-10-09 10:16
驱动异步方法,传入IRP后:
1. 如果可以立即完成,完成IRP(用IoCompleteIrp()) 2. 如果不能立即完成,用:IoPendingIrp(),且返回STATUS_PENDING,在设备扩展里保存这个IRP,等待可以完成时再返回之. 3. 在DispatchCleanUp()里要完成还在等待的irp,否则DispatchClose()不被调用 Win32里.CreateFile()要用 FILE_FLAG_OVERLAPPED属性,DeviceIoControl()时要加OVERLAPPED ov变量,如果返回失败用GetLastError()得到原因,如果是ERROR_IO_PENDING则用WaitForSingleObject( &ov.hEvent, INFINITE );等待它完成. |
|
地板#
发布于:2003-10-09 10:49
驱动异步方法,传入IRP后: 我用的是GetOverlappedResult,没有用WaitForSingleObject。 我是这样的代码 1、在驱动程序的设备扩展中定义一个IRP变量,并在适当时候(调用IoCreateDevice初始化设备扩展后)初始化其为NULL。如 PIRP UserMessageIrp; 2 case IOCTL_DRIVER_USERMESSAGE Irp->IoStatus.Status = STATUS_PENDING; Irp->IoStatus.Information = 0; IoMarkIrpPending(Irp); IoSetCancelRoutine(Irp,DriverUserMessageCancelIrp);//见5 deviceExtension->UserMessageIrp = Irp; return STATUS_PENDING; 3 定义IRP的Cancel例程,这是在应用程序要退出而驱动程序并没有完成该IRP时调用。 VOID DriverUserMessageCancelIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION deviceExtension; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; IoReleaseCancelSpinLock(Irp->CancelIrql); // If this is our queued read, then unqueue it if( Irp==deviceExtension->UserMessageIrp) { deviceExtension->UserMessageIrp = NULL; } // Whatever Irp it is, just cancel it Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp,IO_NO_INCREMENT); } 我用的是TigerZD的例子,是不是我没有用waitforsingobject呢,我再调试。你有更详细的代码吗。有的话能否发到我的邮箱lioniamhero@yahoo.com.cn |
|
地下室#
发布于:2003-10-09 11:33
驱动好像没有问题.win32里我是把WaitForSingleObject()放在GetOverlappedResult()前面调用的.
// 读数据的线程 UINT ThreadRead( LPVOID wParam ) { PPORT_PARAM pPortParam; DWORD dwBytesRet,dwError,dov; BOOL bResult; pPortParam = (PPORT_PARAM)wParam; pPortParam->m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); ResetEvent(pPortParam->m_ov.hEvent ); pPortParam->m_ov.Offset = 0; pPortParam->m_ov.OffsetHigh = 0; bResult = ReadFile( pPortParam->m_hFile, pPortParam->m_bufferReceive, 10,//sizeof( pPortParam->m_bufferReceive ), &dwBytesRet, &pPortParam->m_ov ); // 接收 if( !bResult ) { dwError = GetLastError(); switch( dwError ) { case ERROR_IO_PENDING: { // asynchronous i/o is still in progress // Proceed on to GetOverlappedResults(); WaitForSingleObject( &pPortParam->m_ov.hEvent, INFINITE ); bResult = GetOverlappedResult(pPortParam->m_hFile, // Handle to COMM port &pPortParam->m_ov, // Overlapped structure &dov, // Stores number of bytes sent TRUE); // Wait flag if( bResult ) { } break; } default: break; } } Sleep(5000); // 测试用,一般是一个循环的读 return 0; } typedef struct _PORT_PARAM // 串口结构 { HANDLE m_hFile; ULONG m_ulReadError; UCHAR m_bufferSend[NUMBER_SEND]; UCHAR m_bufferReceive[NUMBER_SEND*2]; int m_nBaudRate; ULONG m_nSendNumber; // 发送个数 ULONG m_nReceiveNumber; // 接收个数 OVERLAPPED m_ov; // 重叠io _PORT_PARAM() { int count = 0; m_hFile = INVALID_HANDLE_VALUE; m_nBaudRate = CBR_115200; m_ulReadError = 0; m_nSendNumber = m_nReceiveNumber = 0; } ~_PORT_PARAM() { if( m_hFile != INVALID_HANDLE_VALUE ) CloseHandle( m_hFile ); } } PORT_PARAM,*PPORT_PARAM; |
|
论坛版主
![]() |
5楼#
发布于:2003-10-09 17:03
这个嘛,我试验的结论是:
deviceiocontrol做动作,不管你给不给overlapped,只要你驱动返回来status_pending,都要遭挂起,直到做完动作,有iocompleterequest(),结束你挂起的irp的时候,才继续动作,所以返回status_pending的话后面的getoverlappedresult和waitforsingleobject都没有用,因为在deviceiocontrol就挂起了,等deviceiocontrol解挂,自然是下面iocompleterequest了,这样,overlapped肯定也是有信号了,所以你要直接返回的话要嘛就写status_success或者错误状态都可以。 你做动作做完了发啥子状态回去可以自己控制,按你自己的需要来做,你如果发起写或者读操作,也可以直接写status_success就回去,不要等它,等是现在设备忙,暂时做不了现在的irp的时候才等三,又不每次都等:),它完了中断自己会打过来,你中断里面弄个信号出来应用程序就晓得动作完了,象pending irp排队是为了使驱动用起来愉快的,可以接受很多irp,上层不管设备的状态而已,你可以自己控制你要哪方面更愉快三:) |
|
6楼#
发布于:2003-10-10 08:04
感谢。给分
|
|
7楼#
发布于:2003-10-10 21:42
用异步的话,怎么样都会把应用程序挂起的,那我应用程序如何控制驱动和设备之间的数据收发呢。我要做实时数据采集啊。比如我要停止采集,但驱动一直在接收数据没有返回,应用不就死在那吗。
|
|
论坛版主
![]() |
8楼#
发布于:2003-10-13 16:59
你的应用不要来就写成个死循环三,你可以设个标志,在采集完一次以后,检查标志是否是还要采集,如果上层决定不才了,就把标志设成某个状态,循环就可以退出来了
|
|