jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
阅读:1658回复:16

关于异步irp的处理!

楼主#
更多 发布于:2003-08-01 15:24
我在驱动程序里建立了一个URB,如下:
urb = D12_BuildAsyncRequest(DeviceObject,Irp,pipeHandle, TRUE);
然后设置完成例程:
IoSetCompletionRoutine(Irp,
D12_AsyncReadWrite_Complete,
context,
TRUE,
TRUE,
TRUE);
之后把这个IRP发送到下层驱动:
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

问题:
1,如果这个IRP完成的话它会自动调用我的完成例程D12_AsyncReadWrite_Complete,然后我在完成里成立处理返回的数据是吗?
2,前面那个过程我可以循环进行吗?也就是说我发送多个IRP下去排队,那么每次队列里最多有多少个这样的IRP呢?应该有什么限制吧。
3,如果我上层应用程序是用ReadFile()来读取数据,那么这个请求发送下去之后该函数是不是会立即返回呢?也就是说不等待驱动里面的irp完成并且把数据放到我传下去的缓冲区里?


因为使用同步操作出现丢失数据现象,所以才是用异步操作,希望做过的同仁给点指导,多谢多谢!

最新喜欢:

hunterforpighunter...
swf2003
驱动中牛
驱动中牛
  • 注册日期2003-02-13
  • 最后登录2011-10-28
  • 粉丝1
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-08-01 15:41
re
1、是在完成例程中处理返回的数据。
2、可以循环,但要修改一下,比如增加一个 DPC ,在完成例程中给 DPC 队列中增加一个对象,在 DPC 处理中发 IRP。
3、上层应用程序用ReadFile()来读取数据,可以同步处理,即处理完立即返回。
我觉得在 2 中你可以一直循环读取数据,放到块缓冲区中,当调用ReadFile()时,就直接从缓冲区中取数据,这样就可以同步处理了,一些实时处理都是类似这样的。

希望对你有帮助!
你的认可是对我最大的鼓励!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-08-01 15:53
swf2003:
我刚才看了一些以前的贴子,原来可以在应用程序里循环进行,也就是我用OVERLAPPED方式打开设备,然后使用readfile()把缓冲区和要请求的数据发给驱动,采用异步方式,这样我的readfile可以立即返回,等待overlapped事件发生,此处我可以另开一个线程处理这个事件吗?

我的主线程一直发送readfile命令,这样就不会出现同步irp中返回数据后有一个时间驱动没有事情做的现象了,我发现在每个irp处理过程中数据时不会丢是的,但是这个irp返回到下一个irp发送下去之间的时间里会有数据丢失!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-08-01 15:59
下面是以前财神给别人会的贴子,但是有些内容我有些疑问:
***********************************************
应用层:
HANDLE FileIOWaiter = CreateEvent( NULL, TRUE, FALSE, NULL);
OVERLAPPED ol;
ol.Offset = 0;
ol.OffsetHigh = 0;
ol.hEvent = FileIOWaiter;

if(!ReadFile(hDEV,
Buffer,
Length,
&nReadBytes,
&ol))
{
if(GetLastError()==ERROR_IO_PENDING)
{
while(WaitForSingleObject(FileIOWaiter, 100)==WAIT_TIMEOUT)
{
}
GetOverlappedResult(hDEV, &ol, &nReadBytes, FALSE);
}
}
驱动中用IoMarkIrpPending(Irp);挂起该IRP并在适当的时候调用IoCompleteRequest(Irp, IO_NO_INCREMENT);
***************************************************************
我能不能把如上的程序分成两个线程,一个线程只发ReadFile,一个线程处理overlapped事件,可是我如何知道这个事件发生了呢?就是通过函数GetOverlappedResult(hDEV, &ol, &nReadBytes, FALSE);查询吗?
swf2003
驱动中牛
驱动中牛
  • 注册日期2003-02-13
  • 最后登录2011-10-28
  • 粉丝1
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-08-01 16:36
申请两个 URB 一个 URB 申请一个 IRP,循环使用,这是我们以前用过的,不会有数据丢失。其实你想想对于一个实时设备,如果驱动不连续的取数据,肯定会丢的,所以不管有无 IRP_MJ_READ 来,我们都要从设备取数据的,当有 IRP_MJ_READ 请求,这时缓冲区就有数据,所以我们就可以直接处理然后返回,我觉得这样处理简单。
你的认可是对我最大的鼓励!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-08-01 16:49
你的意思我明白,但是实际操作我就不大会了,我初步的想法是多发几次readfile下去(例如4个,每个申请64k的数据),这样就会有多个irp排队了,然后我在主机方判断overlapped事件,完成一个我就把回来的数据存储,然后再把这个发下去,只要驱动里有irp排队我的数据就不会丢失了,你说是吗?

我觉得这样对我来说比较简单一点,因为我对驱动的核心思想还不大明白,所以有很多东西我喜欢在应用程序里面解决。

另外我的应用程序不启动的话设备方是不会有数据的,数据产生是通过readfile来启动的,因此和你那种情况不大相同,不过我觉得你的方法却是很好,可是估计我目前还实现不了,因为我现在完全是靠例子来完成我的工作,没有例程我就什么也干不了,最主要的原因是我们系统的学习驱动,只是临时抱佛脚! :(
swf2003
驱动中牛
驱动中牛
  • 注册日期2003-02-13
  • 最后登录2011-10-28
  • 粉丝1
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-08-01 17:27
全部靠用户态处理,那你就要用异步处理,或者同步处理也行,但要创建一个工作线程来发 ReadFile 。
你的认可是对我最大的鼓励!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-08-01 21:42
同步处理也行吗?如果是同步处理的话我发ReadFile下去,如果的不到数据应用程序就会在这个函数处等待的,难道我在CreatFile的时候只要设置了overlapped标志就能让ReadFile立即返回吗?好像不行吧。
swf2003
驱动中牛
驱动中牛
  • 注册日期2003-02-13
  • 最后登录2011-10-28
  • 粉丝1
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-08-02 06:28
同步处理,如果得不到数据应用程序就会在这个函数处等待的,不接受任何相应,这就是我为什么建议你创建一个工作线程的原因。
你的认可是对我最大的鼓励!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-08-02 12:53
我之前已经试过双线程了,一个线程用readfile读数,一个用来存数,但还是不行,因为在一个readfile 返回倒下一个readfile请求发下去在到底程驱动进行执行是需要1/10毫秒量级的时间损耗的,而在这段时间内我设备的端点已经溢出了!所以我现在只能考虑用异步的了,你那里有没有这段程序的例子,只需要处理异步请求得这一段代码即可,有的话请发到我邮箱里,多谢了!
swf2003
驱动中牛
驱动中牛
  • 注册日期2003-02-13
  • 最后登录2011-10-28
  • 粉丝1
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-08-03 02:05
所以要在驱动中做!
你的认可是对我最大的鼓励!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2003-08-03 17:15
分都给你了 :D
williamwilliam
驱动牛犊
驱动牛犊
  • 注册日期2003-02-28
  • 最后登录2005-11-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2003-08-05 14:24
jinghuiren您好!
  您的问题解决了吗?
  我现在碰到了同样的问题,还望大侠指点一下。
  我用的是CY7C68013 FX2, driver 是 ezusb.sys.
  ezusb.sys应该是不支持OVERLAPED的,您在USER MODE 解决了问题吗?
mojun163@163.com
HONGLIN
驱动牛犊
驱动牛犊
  • 注册日期2002-04-04
  • 最后登录2010-03-17
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望12点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2003-08-06 13:12
老哥:驱动里能够区分同步异步吗?我认为是无满足条件则先Pending,在就Timeout完成!
不再困惑
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2003-08-06 14:09
能区分的
ezusb里是不支持overlapped,有两种方法,一种是你把ioctl的函数ezusb_read_write()改成异步模式的,一种是你参考ddk里的bulkusb的例子增加一个read()和一个write()函数,对应功能码为IRP_MJ_READ和IRP_MJ_WRITE,在这两个函数里实现异步irp。
williamwilliam
驱动牛犊
驱动牛犊
  • 注册日期2003-02-28
  • 最后登录2005-11-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2003-08-07 09:02
jinghuiren您好!
  我这样理解对吗?:
     DDK下带的USBBULK,说是ASYNC的, 但也只是 一个BULK_READ 分成了几个ASYNC 的 URB,但应用软件调BULK_READ 还是要一个个来.不能OVERLAPED。 两次调BULK_READ 之间还是要丢数据. 对吗?
我对驱动不熟, 您能否提供一些代码或例子?
  非常感谢您的帮助。
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2003-08-07 11:53
没有呀,ddk下的bulkusb里的bulk_read和bulk_write是异步的,支持overlapped的,就象我前面转贴别人的贴子,在应用程序里设置一个overlapped,而驱动里:“驱动中用IoMarkIrpPending(Irp);挂起该IRP并在适当的时候调用IoCompleteRequest(Irp, IO_NO_INCREMENT);”当这个irp完成时,应用程序里的overlapped会自动被设置为信号态,你可以在另一个线程中收数据,同时你的主线程可以不管上一个irp是否结束就发送下一个irp下去的,但是由于驱动堆栈是有限的,因此你不能发太多的irp下去。
游客

返回顶部