我是靠谱客的博主 友好含羞草,最近开发中收集的这篇文章主要介绍(五)NT驱动基础——分发函数的三种读写方式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

要知道内核模式地址和用户模式地址是不可以直接互相读写的,那么它们之间的数据传递,是通过请求作为载体。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驱动基础——分发函数的三种读写方式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部