lioniamhero
驱动小牛
驱动小牛
  • 注册日期2003-05-31
  • 最后登录2005-10-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2323回复:8

关于DeviceIoControl异步的问题

楼主#
更多 发布于:2003-10-07 18:40
关于DeviceIoControl异步的问题
   我想用DeviceIoControl异步方式来向驱动来读取,目的是让它立即返回,但我调试的还是要等它完成了才返回 ,我是按相关例子在CreateFile( ) 和DeviceIoControl 中的参数都设置好了啊,是不是驱动中要改吗。要让它立即返回还要注意什么呢。

最新喜欢:

hunterforpighunter...
lioniamhero
驱动小牛
驱动小牛
  • 注册日期2003-05-31
  • 最后登录2005-10-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-10-08 14:58
大侠们帮我看看吧
qinxg
驱动小牛
驱动小牛
  • 注册日期2002-11-15
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分37分
  • 威望27点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
板凳#
发布于: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 );等待它完成.

lioniamhero
驱动小牛
驱动小牛
  • 注册日期2003-05-31
  • 最后登录2005-10-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-10-09 10:49
驱动异步方法,传入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 );等待它完成.

 

  我用的是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
qinxg
驱动小牛
驱动小牛
  • 注册日期2002-11-15
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分37分
  • 威望27点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
地下室#
发布于: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;
wxl_50685330
论坛版主
论坛版主
  • 注册日期2002-11-19
  • 最后登录2018-09-25
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望521点
  • 贡献值0点
  • 好评度419点
  • 原创分0分
  • 专家分0分
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,上层不管设备的状态而已,你可以自己控制你要哪方面更愉快三:)
根据地的兄弟们,团结就是力量
lioniamhero
驱动小牛
驱动小牛
  • 注册日期2003-05-31
  • 最后登录2005-10-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-10-10 08:04
感谢。给分
lioniamhero
驱动小牛
驱动小牛
  • 注册日期2003-05-31
  • 最后登录2005-10-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-10-10 21:42
用异步的话,怎么样都会把应用程序挂起的,那我应用程序如何控制驱动和设备之间的数据收发呢。我要做实时数据采集啊。比如我要停止采集,但驱动一直在接收数据没有返回,应用不就死在那吗。
wxl_50685330
论坛版主
论坛版主
  • 注册日期2002-11-19
  • 最后登录2018-09-25
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望521点
  • 贡献值0点
  • 好评度419点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-10-13 16:59
你的应用不要来就写成个死循环三,你可以设个标志,在采集完一次以后,检查标志是否是还要采集,如果上层决定不才了,就把标志设成某个状态,循环就可以退出来了
根据地的兄弟们,团结就是力量
游客

返回顶部