用户层与内核层通讯——控制码方式通讯
前言:
此文是记录我遇到的问题及解决办法
环境相关:
使用的直接读写方式,这种方式会创建一个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); }
直面挫折,顽强生长