pastroal
驱动牛犊
驱动牛犊
  • 注册日期2002-03-06
  • 最后登录2005-09-30
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2099回复:16

MDL

楼主#
更多 发布于:2002-11-20 09:14
其实我到现在都没彻底搞明白MDL的含义是什么。
但我知道它能够加快数据传输的速度,所以我用它。
我现在有一个可有的USB客户驱动程序,他的读写是基于BUFFER方式的,我现在想把它改成MDL的方式。
以下是我的主要代码:
NTSTATUS
EbskUsb_Read(
IN PDEVICE_OBJECT DeviceObject ,
IN PUCHAR InputData,
IN ULONG TranLen,
IN ULONG *pRealdataLen ,
IN UCHAR ReadType
)
{
1 //
// Alloc and initialize URB
//...urb里面填了读的长度,管道Handle,MDL和Buffer没填。
2
nextStack->Parameters.Others.Argument1 = urb;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;

mdl = IoAllocateMdl(InputData,
TranLen,
FALSE,
TRUE,
Irp);

MmBuildMdlForNonPagedPool(mdl);

urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = mdl;

3 IoSetCompletionRoutine(Irp,EbskUsb_Read_Complete,IrpCon,TRUE,TRUE, TRUE);
status = IoCallDriver(deviceExtension->NextLowerDriver, Irp );
return status;

}
上面函数的InputData是我在驱动中ExAllocatePool出来的一段缓冲区



NTSTATUS
EbskUsb_Read_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
....
IoFreeMdl(IrpCon->mdl);
EBSKUSB_ExFreePool (urb);
EBSKUSB_ExFreePool (Context);

}


但是我上面带mdl的IRP发下去就在也没到EbskUsb_Read_Complete里面来,我怀疑是我没用对。

大侠们帮我看看MDL是不是咋用的?救命阿!



 

最新喜欢:

chilichili
ysy
ysy
驱动中牛
驱动中牛
  • 注册日期2002-02-18
  • 最后登录2008-08-25
  • 粉丝0
  • 关注0
  • 积分201分
  • 威望29点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-11-20 13:56
可参考DDK里的Sample,那里面就是用Mdl传输的,有详细的代码。
pastroal
驱动牛犊
驱动牛犊
  • 注册日期2002-03-06
  • 最后登录2005-09-30
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-11-20 15:30
你是说DDK里面的USBBLUK吗?我看的就是那个阿
还有比别的例子吗?
ysy
ysy
驱动中牛
驱动中牛
  • 注册日期2002-02-18
  • 最后登录2008-08-25
  • 粉丝0
  • 关注0
  • 积分201分
  • 威望29点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-11-20 16:21
那个例子有什么问题吗?我用过一切正常!硬件肯定没有问题吗?
pastroal
驱动牛犊
驱动牛犊
  • 注册日期2002-03-06
  • 最后登录2005-09-30
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-11-21 11:02
那个例子里面上面下来的IRP就是MDL的,我现在是想把自己在驱动力申请的一块缓冲区以MDL的方式发下去,不知道怎么做。
edriver
驱动小牛
驱动小牛
  • 注册日期2002-03-04
  • 最后登录2006-09-15
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-11-21 11:19
其实你可以在driver和app实现buffer共享呀。基本上算得上MDL吧?
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-11-21 12:52
其实我到现在都没彻底搞明白MDL的含义是什么。
但我知道它能够加快数据传输的速度,所以我用它。
我现在有一个可有的USB客户驱动程序,他的读写是基于BUFFER方式的,我现在想把它改成MDL的方式。
以下是我的主要代码:
NTSTATUS
EbskUsb_Read(
IN PDEVICE_OBJECT DeviceObject ,
IN PUCHAR InputData,
IN ULONG TranLen,
IN ULONG *pRealdataLen ,
IN UCHAR ReadType
)
{
1 //
// Alloc and initialize URB
//...urb里面填了读的长度,管道Handle,MDL和Buffer没填。
2
nextStack->Parameters.Others.Argument1 = urb;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;

mdl = IoAllocateMdl(InputData,
TranLen,
FALSE,
TRUE,
Irp);

MmBuildMdlForNonPagedPool(mdl);

urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = mdl;

3 IoSetCompletionRoutine(Irp,EbskUsb_Read_Complete,IrpCon,TRUE,TRUE, TRUE);
status = IoCallDriver(deviceExtension->NextLowerDriver, Irp );
return status;

}
上面函数的InputData是我在驱动中ExAllocatePool出来的一段缓冲区



NTSTATUS
EbskUsb_Read_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
....
IoFreeMdl(IrpCon->mdl);
EBSKUSB_ExFreePool (urb);
EBSKUSB_ExFreePool (Context);

}


但是我上面带mdl的IRP发下去就在也没到EbskUsb_Read_Complete里面来,我怀疑是我没用对。

大侠们帮我看看MDL是不是咋用的?救命阿!



  


MDL的全称是:
Mmemory descripotr list, DDK中解释如下:
An opaque structure, defined by the Memory Manager, that uses an array of physical page frame numbers (PFNs) to describe the pages that back a virtual memory range.

Tom_lyd
pastroal
驱动牛犊
驱动牛犊
  • 注册日期2002-03-06
  • 最后登录2005-09-30
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-11-21 15:26
版主,你就这么回我啊,我又不是没装过DDK
ysy
ysy
驱动中牛
驱动中牛
  • 注册日期2002-02-18
  • 最后登录2008-08-25
  • 粉丝0
  • 关注0
  • 积分201分
  • 威望29点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-11-21 15:28
哈,斑竹在搞笑,别当真!
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2002-11-21 15:32
对USB不熟悉,IOCTL_INTERNAL_USB_SUBMIT_URB
定义的是direct的方式吗?
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-11-21 15:54
呵呵
其实我到现在都没彻底搞明白MDL的含义是什么
Tom_lyd
ydyuse
驱动老牛
驱动老牛
  • 注册日期2002-07-25
  • 最后登录2005-03-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-11-21 16:19
我再抄一段给你,看是否有帮助:



[编辑 -  11/25/02 by  ydyuse]
生命驱动,活力无限!
pastroal
驱动牛犊
驱动牛犊
  • 注册日期2002-03-06
  • 最后登录2005-09-30
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2002-11-22 08:49
还是很感谢大家的帮助,我今天再看看,给分先。
eiferxia
驱动牛犊
驱动牛犊
  • 注册日期2002-11-23
  • 最后登录2005-06-25
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2002-11-25 12:49
若对用户内存直接作DMA的话MDL尤为重要。因为用户传给驱动的连续虚拟内存在物理上往往是不连续的。在利用scatter and gether技术时,DMA需要这些物理上不连续的各个内存块的首址以便一次完成对用户内存直接传送。这些内存块的首址便是从用户传来的MDL中得来的。
jansen
驱动小牛
驱动小牛
  • 注册日期2001-10-21
  • 最后登录2007-10-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2002-11-25 19:08
贴上一点摘录,不知是否有帮助!
以下为引用:
在用户模式及核心模式之间共享内存

MmMapLockedPages 方法:设备驱动程序分配共享内存


在这种方法中,驱动程序通过 MmAllocateContiguousMemory 或 ExAllocatePoolXxx 函数分配内存,创建并建立描述缓冲区的 MDL,并使用 MmMapLockedPages 把内存映射到用户进程地址空间中。用户应用程序可以使用由 MmMapLockPages 返回的虚拟地址直接访问系统内存。

由于应当在访问内存的进程上下文中完成映射,所以此方法只能用于单层结构的驱动程序,这时可以保证 dispatch 例程在调用进程上下文中运行。您可以在任意数量的用户过程地址空间上映射同一个系统缓冲区。不过,应当设计一种保护机制,使驱动程序及所有应用程序对内存的访问同步。进一步说,应当在终止进程之前或者一旦使用完缓冲区就在映射缓冲区的相同进程上下文中取消缓冲区的映射。下面介绍将驱动程序缓冲区映射至某个用户进程时需采取的步骤:


首先如下分配内存:

      SystemVirtualAddress = MmAllocateContiguousMemory(NumberOfBytes,
      HighestAcceptableAddress); 或
      SystemVirtualAddress = ExAllocatePool(PoolType, NumberOfBytes);

如下分配一个 MDL:

      Mdl = IoAllocateMdl(SystemVirtualAddress, NumberOfBytes, FALSE,
      FALSE, NULL);

建立 MDL 以描述内存页。如果已经分配了非页面缓冲池中的内存,请使用:
 
      MmBuildMdlForNonPagedPool(Mdl);
如果分配了页面缓冲池中的内存,请使用:
 
      MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
如下将锁定的页面映射至进程的用户地址空间中:

      UserVirtualAddress = MmMapLockedPages(Mdl, UserMode);

前三步可以在 DriverEntry 或 Dispatch 例程中完成。但是,将缓冲区映射至用户地址空间的最后一步,应当在运行于调用进程上下文的某个例程(通常是单层驱动程序的 dispatch 例程)中完成。

您可以在某个提高的 IRQL 级及任何进程上下文(即中断服务例程 (ISR) 及延迟过程调用 (DPC))的驱动程序中使用 SystemVirtualAddress,在应用程序或运行正确进程上下文的驱动程序中使用 UserVirtualAddress。

按照下列步骤取消映射并释放缓冲区:
首先从用户地址空间中取消页面映射。应在映射 UserVirtualAddress 的进程上下文中运行时调用函数:
      MmUnmapLockedPages(UserVirtualAddress, Mdl);
如果使用 MmProbleAndLockPages 锁定了页面,则使用以下函数解锁:
      MmUnlockPages(Mdl)
释放 MDL:
      IoFreeMdl(Mdl);
释放系统内存:
      MmFreeContiguousMemory(SystemVirtualAddress); 或
      ExFreePool(SystemVirtualAddress);
rich
pastroal
驱动牛犊
驱动牛犊
  • 注册日期2002-03-06
  • 最后登录2005-09-30
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2002-11-26 08:40
这位兄弟是在哪里摘录的?是哪本书阿?
wangyupup
驱动牛犊
驱动牛犊
  • 注册日期2002-09-28
  • 最后登录2007-10-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2002-11-26 09:39
请问jansen, 是在那里摘的? 很想看的说
游客

返回顶部