• 50、Windows驱动程序模型设计笔记(八),IRP


    3、派遣例程的职责

    •派遣函数立即完成该IRP。

    •把该IRP传递到处于同一堆栈的下层驱动程序。

    •排队该IRP以便由这个驱动程序中的其它例程来处理。

        每个设备对象都自带一个请求队列对象,下面是使用这个队列的标准方法:

    NTSTATUS DispatchXxx(...)

    {

    ...

    IoMarkIrpPending(Irp);

    IoStartPacket(device, Irp, NULL, NULL);

    return STATUS_PENDING;

    }

    一旦我们调用了IoStartPacket函数,就不要再碰IRP。因为在该函数返回之前,IRP可能已经被完成并且其占用的内存可能被释放,而我们拥有的该IRP的指针也许是无效的

    4、StartIo例程

    每处理一个IRP,I/O管理器就调用一次StartIo例程。StartIo的工作是就着手处理IRP。

    5、中断服务例程

    用IoConnectInterrupt函数“钩住”一个中断,该函数的一个参数就是ISR的地址。一个ISR最可能做的事就是调度DPC例程(推迟过程调用)。而DPC的目的就是让你做某些事情,如调用IoCompleteRequest。

    . IoCompleteRequest的优先级推进值

    推进值常量

    优先级推进值

    IO_NO_INCREMENT

    0

    IO_CD_ROM_INCREMENT

    1

    IO_DISK_INCREMENT

    1

    IO_KEYBOARD_INCREMENT

    6

    IO_MAILSLOT_INCREMENT

    2

    IO_MOUSE_INCREMENT

    6

    IO_NAMED_PIPE_INCREMENT

    2

    IO_NETWORK_INCREMENT

    2

    IO_PARALLEL_INCREMENT

    1

    IO_SERIAL_INCREMENT

    2

    IO_SOUND_INCREMENT

    8

    IO_VIDEO_INCREMENT

    1

        不要以专用状态代码STATUS_PENDING来完成一个IRP。派遣例程经常要使用STATUS_PENDING代码作为返回值,但你决不能在IoStatus.Status中设置这个值。

    6、完成例程

        IoSetCompletionRoutine将把完成例程地址和上下文参数安装到下一个IO_STACK_LOCATION中,即下一层驱动程序将在那个堆栈单元中找到这些参数。因此,最底层的驱动程序不应该安装一个完成例程。

        完成例程通常在DISPATCH_LEVEL级和任意线程上下文中被调用,但有时也在PASSIVE_LEVEL或APC_LEVEL级被调用。为了适应大多数情况(DISPATCH_LEVEL),完成例程应存在于非分页内存中,并且仅使用可在DISPATCH_LEVEL级上调用的服务例程。然而,为了适应在低级IRQL上调用该例程的可能情况,完成例程不应调用像KeAcquireSpinLockAtDpcLevel这样的函数,因为这些函数假定开始执行于DISPATCH_LEVEL级上。

        在完成例程内部,一个IoGetCurrentIrpStackLocation调用将获得上一层堆栈单元的指针。上层堆栈单元的完成例程不应该依赖任何下层堆栈单元中的内容。为了加强这个规则,IoCompleteRequest在调用完成例程前清除了下一个堆栈单元中的大部分内容。

    wps_clip_image-27419

    if (Irp->PendingReturned)

    IoMarkIrpPending(Irp);

        所有不返回STATUS_MORE_PROCESSING_REQUIRED状态的完成例程都需要这两行代码。

    7、取消I/O请求

        为了在内核模式中取消一个请求,IRP的创建者需调用IoCancelIrp函数。如果某线程终止时,它发出的请求仍然未完成,则操作系统自动为每个IRP调用IoCancelIrp。用户模式应用程序调用CancelIo函数可以取消给定线程发出的所有未完成的异步操作。IoCancelIrp仅仅是简单地设置IRP的Cancel标志位然后调用IRP的取消例程。即:它并不知道你在是否修改过IRP指针,也不知道你是否正在处理这个IRP,所以它必须依靠一个你提供的取消例程来做大部分IRP取消工作。

    关于取消IO更多的关于多CPU的讨论,见参考文献[1]。

    [1] Windows驱动程序模型设计

  • 相关阅读:
    H.264 RTP PAYLOAD 格式
    ARM:移动GPU往PC GPU效能迈进
    汪墩一中复校设想
    jconsole 和jvisualVM 监控远程 spring boot程序
    jenkins 登录远程机器并执行脚本,脚本中有后台执行的程序无法执行解决方法。
    linux下的抓包工具tcpdump
    adb logcat查看某个进程的输出日志
    Flask-SQLAlchemy 中多表链接查询(不使用外键)
    使用cnpm 安装vue.js
    Jmeter在非GUI环境下传递参数(命令行&Jenkins配置)
  • 原文地址:https://www.cnblogs.com/mydomain/p/1926544.html
Copyright © 2020-2023  润新知