驱动的请求处理

开发一个驱动要有可能要处理各种IRP。但是本书范围内,只处理为了应用程序和驱动交互而产生的IRP。IRP的结构非常复杂,但是目前的需求下没有必要去深究它。应用程序为了和驱动通信,首先必须打开设备。然后发送或者接收信息。最后关闭它。这至少需要三个IRP:第一个是打开请求。第二个发送或者接收信息。第三个是关闭请求。

IRP的种类取决于主功能号。主功能号就是前面的说的DRIVER_OBJECT中的分发函数指针数组中的索引。打开请求的主功能号是IRP_MJ_CREATE,而关闭请求的主功能号是IRP_MJ_CLOSE。

如果写有独立的处理IRP_MJ_CREATE和IRP_MJ_CLOSE的分发函数,就没有必要自然判断IRP的主功能号。如果像前面的例子一样,使用一个函数处理所有的IRP,那么首先就要得到IRP的主功能号。IRP的主功能号在IRP的当前栈空间中。

IRP总是发送给一个设备栈。到每个设备上的时候拥有一个“当前栈空间”来保存在这个设备上的请求信息。读者请暂时忽略这些细节。下面的代码在MyDispatch中获得主功能号,同时展示了几个常见的主功能号:

    NTSTATUS MyDispatchFunction(PDEVICE_OBJECT device,PIRP irp)
    {
        // 获得当前irp调用栈空间
        PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
        NTSTATUS status = STATUS_UNSUCCESSFUL;
        swtich(irpsp->MajorFunction)
        {
        // 处理打开请求
        case IRP_MJ_CREATE:
            ……
            break;
        // 处理关闭请求
        case IRP_MJ_CLOSE:
            ……
            break;
        // 处理设备控制信息
        case IRP_MJ_DEVICE_CONTROL:
            ……
            break;
        // 处理读请求
        case IRP_MJ_READ:
            ……
            break;
        // 处理写请求
        case IRP_MJ_WRITE:
            ……
            break;
        default:
            …
            break;
        }
        return status;
    }

用于与应用程序通信时,上面这些请求都由应用层API引发。对应的关系大致如下:

应用层调用的API 驱动层收到的IRP主功能号
CreateFile IRP_MJ_CREATE
CloseHandle IRP_MJ_CLOSE
DeviceIoControl IRP_MJ_DEVICE_CONTROL
ReadFile IRP_MJ_READ
WriteFile IRP_MJ_WRITE

了解以上信息的情况下,完成相关IRP的处理,就可以实现应用层和驱动层的通信了。具体的编程在紧接后面的两小节里完成。

取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

Powered by bytekits.com,汇天下文字,成非凡梦想!!!