comealong
驱动牛犊
驱动牛犊
  • 注册日期2003-04-30
  • 最后登录2012-01-19
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望105点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
阅读:1972回复:11

请问完成例程为什么要这么做?

楼主#
更多 发布于:2004-12-10 09:05
    // 这个标志取的当前stack location 的 control 标志 SL_PENDING_RETURNED
    // IoComleteRequest调用完成例程前,会清control,
    // 但后面又用IoMarkIrpPending设置,
    // 为什么要这么做?
    if( Irp->PendingReturned ) {

        // 这里, 都已经调用IoComleteRequest了 还标志成挂起,不明白
        // 那什么时候, 才能算完呢
        IoMarkIrpPending( Irp );

    }
    return Irp->IoStatus.Status;

    // 感觉WDM即限制了程序员的自由, 却没有给出一个清析的结构

最新喜欢:

agchenagchen
aethercat
驱动牛犊
驱动牛犊
  • 注册日期2003-08-20
  • 最后登录2005-06-11
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-12-10 15:09
推荐仔细看一下《Programming the Microsoft Windows Driver Model 》这本书,里面关于I/O请求包的一章可以给你很好的解释
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
板凳#
发布于:2004-12-10 17:22
异步和同步是不一样的.
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
comealong
驱动牛犊
驱动牛犊
  • 注册日期2003-04-30
  • 最后登录2012-01-19
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望105点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-12-12 10:13

虽然楼上二位的回复说了等于没说
不过,还是谢谢了
tigerL
驱动小牛
驱动小牛
  • 注册日期2003-12-24
  • 最后登录2008-10-28
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望23点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-12-12 23:53

虽然楼上二位的回复说了等于没说
不过,还是谢谢了



就是,不知他们是知还是不知。
省元坊
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-12-13 12:12
[quote]
虽然楼上二位的回复说了等于没说
不过,还是谢谢了



就是,不知他们是知还是不知。 [/quote]

因为答案就在《Programming the Microsoft Windows Driver Model 》这本书中,再结合IoCompleteRequest的源码,一切都很明了

简单点说就是IO管理器对irp的处理是不一样的(分为同步完成和异步完成),而IoMarkIrpPending就是用来标记irp是异步完成的。(而不是用来挂起irp的,在派遣例程中返回status_pending才会挂起irp)

至于为什么要调用IoMarkIrpPending,是因为IoCompleteRequest并没有保存irp是如何完成的信息


[编辑 -  12/13/04 by  tooflat]
comealong
驱动牛犊
驱动牛犊
  • 注册日期2003-04-30
  • 最后登录2012-01-19
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望105点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-12-14 14:35
很谢谢tooflat的回答

还有些没明白

IoMarkIrpPending 是在完成例程中调用的
此时都已经调用 IoCompleteRequest了, 这个例程完成这个IRP,
这个时候又把IRP标记成异步完成是什么意思
那IRP什么时候才真正算完呢?

此时完成例程通常会返回什么?

谢了
tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
7楼#
发布于:2004-12-14 23:28
irp的完成并不是一个函数调用就ok的...

比如你发送一个read的irp到某个device...假设你使用buffer的方式.....

那么系统就会为你分配一个缓冲区SystemBuffer...device获取的数据是放到这个buffer里面的....
在device完成这个irp的时候...系统要把SystemBuffer的内容copy到user buffer里面.....

但是user buffer指针只是在发生irp的进程里面才是有效的,(system buffer是任意进程都有效的).....那么
如果irp是同步完成的..也就是说当前进程还是在原来发送irp的进程里面的话...user buffer 指针就是可以直接完成的...IoCompleteRequest只是直接copy就行了....

如果irp是异步完成的..那么很可能当前进程已经不是发送irp的进程了....这个时候的user buffer指针是不正确的...所以copy 操作必须要在发送irp的进程里面执行....kernel通过一个叫apc的技术实现...简单的讲就是引发一个软件中断..排程一个apc object.在以后发生context switch的时候...os会检查将要执行的thread的apc队列,如果不为空就执行这个apc关联的函数...这个函数再进行copy操作....

明白了么...非异步完成的irp必须要排程一个apc routine...
而实际上...使用apc是非常慢的一个操作...
如果同步完成irp..apc是完全可以避免的...

所以IoCompleteRequest会检查SL_PENDING_RETURNED这个标记来决定是否使用apc...如果设置了这个标记...就可能会有一个apc被放置到发送irp的thread的apc队列里面...

所以IoMarkPending就是用来告诉os需要apc的....
而所谓return pending...并不能说明任何的问题...返回值只是给调用者检查的...os并不解释每个dispatch routine的返回值...

最后要说的就是为什么在complete routine里面要markpending..
因为SL_PENDING_RETURNED是一个iostack域的flags...并不是一个irp级的flags...所以每一个stack都有不同的flags..
因为上层调用者大多少情况是不知道irp会不会pending的...决定irp pending的device一般只有一个...他只会设置自己的stack的flags....而上层调用者却不会设置这个flags

你也知道complete routine是发生在apc的前面的..要先complete routine 然后再决定是否需要apc的...
在传递给你的complete routine的时候..你所对应的stack已经被全部zero out的...你调用IoMarkPending的时候其实修改的是你上一个device对应的stack....这点要清楚的认识....

你然后要问...为什么要这样修改呢?因为complete routine会return STATUS_MORE_PROCESSING_REQUIRED....这个时候irp的complete操作就会停止....你要记得你对应的stack已经被全部的zero out了...那用什么表示这个irp是异步完成的呢? 所以你必须要留下一个标记....当然就是你上一个stack的flags了...这也就是调用IoMarkPending的由来...

你要说为什么不使用Irp级别的pending 标记呢....
这个应该是设计上的原因...因为决定一个irp是否pending的只应该是某一个device....而不是任何的device...同时把一个device对应到一个stack也算是一种设计上的方式吧....也或者有我不知道的技术上的原因.....

注意Irp->PendingReturned并不是一个好的保存flags的地方..
因为他其实是根据当前stack的flags的SL_RETURN_PENDING每次在调用complete routine之前设置的....

最后最后...如果当前stack 没有一个complete routine...会不会设置这个pending呢....
答案是会....IoCompleteRequest会完成这个操作....跟你在complete routine里面一样的判断.....只是要check当前还有没有stack没有被unwind.....

以上
comealong
驱动牛犊
驱动牛犊
  • 注册日期2003-04-30
  • 最后登录2012-01-19
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望105点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-12-15 10:21
谢谢大虾指点
tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
9楼#
发布于:2004-12-16 01:13
唔....
你也看到了....
PendingReturn的设置是用complete routine所在的stack的control设置的....
而传递给complete routine的current stack却是其上一个device的stack

我前面说错了...不好意思

调用不调用IoMarkIrpPending的条件并不是你自己device所对应的stack的control值决定的...而是你下一个device的stack的control决定的
comealong
驱动牛犊
驱动牛犊
  • 注册日期2003-04-30
  • 最后登录2012-01-19
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望105点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-12-16 09:23
给大侠发信了
不小得收到没
tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
11楼#
发布于:2004-12-16 13:56
必然没有收到
那个邮箱早就没有用了
加我qq吧

1227963
游客

返回顶部