Windows驱动
+ -

驱动层信息传出

2021-07-01 180 0

驱动主动通知应用和应用通知驱动的通道是同一个。只是方向反过来。应用程序需要开启一个线程调用DeviceIoControl,(调用ReadFile亦可)。而驱动在没有消息的时候,则阻塞这个IRP的处理。等待有信息的时候返回。

有的读者可能听说过在应用层生成一个事件,然后把事件传递给驱动。驱动有消息要通知应用的时候,则设置这个事件。但是实际上这种方法和上述方法本质相同:应用都必须开启一个线程去等待(等待事件)。而且这样使应用和驱动之间交互变得复杂(需要传递事件句柄)。这毫无必要。

让应用程序简单的调用DeviceIoControl就可以了。当没有消息的时候,这个调用不返回。应用程序自动等待(相当于等待事件)。有消息的时候这个函数返回。并从缓冲区中读到消息。

实际上,驱动内部要实现这个功能,还是要用事件的。只是不用在应用和驱动之间传递事件了。

驱动内部需要制作一个链表。当有消息要通知应用的时候,则把消息放入链表中(请参考前面的“使用LIST_ENTRY”),并设置事件(请参考前面的“使用事件”)。在DeviceIoControl的处理中等待事件。下面是一个例子:这个例子展示的是驱动中处理DeviceIoControl的控制码为MY_DVC_OUT_CODE的部分。实际上驱动如果有消息要通知应用,必须把消息放入队列尾并设置事件g_my_notify_event。MyGetPendingHead获得第一条消息。请读者用以前的知识自己完成其他的部分。

    NTSTATUS MyDeviceIoCtrlOut(PIRP irp,ULONG out_len)
    {
        MY_NODE *node;    
        ULONG pack_len;
        // 获得输出缓冲区。
        PVOID buffer = irp->AssociatedIrp.SystemBuffer;

        // 从队列中取得第一个。如果为空,则等待直到不为空。
        while((node = MyGetPendingHead()) == NULL)
        {    
            KeWaitForSingleObject(
                &g_my_notify_event,// 一个用来通知有请求的事件
                Executive,KernelMode,FALSE,0);
        }

        // 有请求了。此时请求是node。获得PACK要多长。
        pack_len = MyGetPackLen(node);
        if(out_len < pack_len)
        {
            irp->IoStatus.Information = pack_len;    // 这里写需要的长度
            irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
               IoCompleteRequest (irp,IO_NO_INCREMENT);
            return irp->IoStatus.Status;
        }

        // 长度足够,填写输出缓冲区。
        MyWritePackContent(node,buffer);
        // 头节点被发送出去了,可以删除了
        MyPendingHeadRemove ();
        // 返回成功
        irp->IoStatus.Information = pack_len;    // 这里写填写的长度
        irp->IoStatus.Status = STATUS_SUCCESS;
           IoCompleteRequest (irp,IO_NO_INCREMENT);
        return irp->IoStatus.Status;
    }

这个函数的处理要追加到MyDeviceIoControl中。如下:

    NTSTATUS MyDeviceIoControl(
        PDEVICE_OBJECT    dev,
        PIRP    irp)
    {
        …
        if(code == MY_DVC_OUT_CODE)
            return MyDeviceIoCtrlOut(dev,irp);
        …
    }

在这种情况下,应用可以循环调用DeviceIoControl,来取得驱动驱动通知它的信息。

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

您的支持,是我们前进的动力!