概述
要知道内核模式地址和用户模式地址是不可以直接互相读写的,那么它们之间的数据传递,是通过请求作为载体。IRP里有三个地方可以描述缓冲区:一个是irp->MdlAddress,一个是irp->UserBuffer,一个是irp->AssociatedIrp.SystemBuffer
这样产生了三种读写方式:1.缓冲区设备读写
2.直接设备读写
3.其他方式设备读写
一、缓冲区设备读写
1.原理:
缓冲区设备读写是应用程序将数据传通过请求递给内核缓冲区,它的优点是,比较简单的解决了用户地址传入的问题,缺点是应用程序与内核之间相互复制数据,效率较差。
2.基本形态
//FunctionBufferWriter_and _Read.cpp
extern "C" NTSTATUS FunctionBufferWriter_and_Read(PDEVICE_OBJECT pDevice,PIRP pIrp)
//要求所传入的参数 pDevice经过pDevice->Flags|=DO_BUFFERED_IO ;//设置设备对象为缓冲区读写
{
PIO_STACK_LOCATION stack=IoGetCurrentIrpStackLocation(pIrp);
//第一步,获取应用程序申请读写数据长度
//若是读处理函数应写为
ULONG ulReadLength=stack->Parameters.Read.Length;
//若是写处理函数应写为
ULONG ulWriteLength=stack->Parameters.Write.Length;
//第二步,由于pIrp->AssociatedIrp.SysstemBuffer是内核与应用程序交互的缓冲区,所以
//若是读处理函数,则内核向pIrp.AssociatedIrp.SystemBuffer写入数据
.....
//如是写处理数据,则内核从pIrp.AssociatedIrp.SystemBuffer读入数据
.....
//第三步,清理工作
pIrp->IoStatus.Status=status;
pIrp->IoStatus.Infomration=ulReadLength或ulWriteLength;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
return status;
}
二、直接设备读写
1.该方法是把应用层的地址映射到内核空间,该方法通过MmGetSystemAddressForMdlSafe()利用pIrp->MdlAddress得到MDL数据结构,这个结构描述了缓冲区,然后将该段内存锁定的缓冲内存,用DDK的三个宏MmGetMdlByteCount,MmGetMdlVirualAddress、MmGetMdlByteOffset取得锁定缓冲区的长度、虚拟地址、偏移量。
2.基本形态
//FunctionDirectWriter_and _Read.cpp
extern "C" NTSTATUS FunctionDirectWriter_and_Read(PDEVICE_OBJECT pDevice,PIRP pIrp)
//要求所传入的参数 pDevice经过pDevice->Flags|=DO_DIRECT_IO ;//设置设备对象为直接读写
{
PIO_STACK_LOCATION stack=IoGetCurrentIrpStackLocation(pIrp);
ULONG ulOffset=MmGetMdlByteOffset(pIrp->MdlAddress);
ULONG ulCount=MmGetMdlByteCount(pIrp->MdlAddress;
//第一步,获取应用程序申请读写数据长度
PVOID pWrite_or_Read_Buffer=MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority); //取得缓冲区映射
//若是读处理函数应写为
ULONG ulReadLength=stack->Parameters.Read.Length;
//若是写处理函数应写为
ULONG ulWriteLength=stack->Parameters.Write.Length;
//第二步,由于pWrite_or_Read_Buffer是内核与应用程序交互的缓冲区,所以
//若是读处理函数,则内核向pWrite_or_Read_Buffer写入数据
.....
//如是写处理数据,则内核从pWrite_or_Read_Buffer读入数据
.....
//第三步,清理工作
pIrp->IoStatus.Status=status;
pIrp->IoStatus.Infomration=ulReadLength或ulWriteLength;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
return status;
}
最后
以上就是友好含羞草为你收集整理的(五)NT驱动基础——分发函数的三种读写方式的全部内容,希望文章能够帮你解决(五)NT驱动基础——分发函数的三种读写方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复