用户层与内核层通讯——控制码方式通讯

前言:

  此文是记录我遇到的问题及解决办法

环境相关:

  使用的直接读写方式,这种方式会创建一个MDL,将用户空间的地址重新映射到了内核空间,这样不会发生拷贝也不会造成地址访问错误。MDL被I/O管理器创建好之后,放置在下面这个字段中

irp->MdlAddress

//获取缓冲区地址需要使用MDL操作函数
MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);

 

    //创建设备对象
    status = IoCreateDevice(
        driver,            //驱动对象(新创建的设备对象所属驱动对象)
        0,                //设备扩展大小
        &devName,        //设备名称
        FILE_DEVICE_UNKNOWN,    //设备类型(未知类型)
        0,                //设备特征信息
        FALSE,            //设备是否为独占的
        &pDevice        //创建完成的设备对象指针
    );

    if (!NT_SUCCESS(status))
    {
        KdPrint(("创建设备失败,错误码:0x%08X\n", status));
        return status;
    }

    //读写方式为直接读写方式
    pDevice->Flags = DO_DIRECT_IO;

  控制码的传输类型为METHOD_OUT_DIRECT

//控制码
#define MYCTLCODE(code) CTL_CODE(FILE_DEVICE_UNKNOWN,0x800+(code),METHOD_OUT_DIRECT,FILE_ANY_ACCESS)

 

问题:

  错将输出内容复制到输入缓冲区(其实是对输出输入缓冲区比较模糊,以为它们共用)

解决:

  输入缓冲区通过irp‐>AssociatedIrp.SystemBuffer获取(无论传递的是哪种方式, 在内核层中都可以通过 irp‐>AssociatedIrp.SystemBuffer 来获取到输入缓冲区)

  输出缓冲区通过MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority)获取

    //获取输入缓冲区(如果存在)
    if (pIrp->AssociatedIrp.SystemBuffer != NULL)
    {
        pInputBuff = pIrp->AssociatedIrp.SystemBuffer;
    }
    //获取输出缓冲区(如果存在)
    if (pIrp->MdlAddress != NULL)
    {
        //获取MDL缓冲区在内核中的映射
        pOutBuff = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
    }

 

posted @ 2020-05-23 14:11  自己的小白  阅读(530)  评论(0编辑  收藏  举报