This article knows the difference between paged memory and nonpaged memory after sharing memory allocation, which changed the problem of my shared memory not being successful.
the use of Ioallocatemdl,mmprobeandlockpages
2012-02-08 10:51:20| Category: Windows kernel Programming | Tags: | font size Big Small subscription
First, one usage of MDL is to provide a way for the driver to access the user-mode data buffer: Direct I/O. That is to say, the MDL tells the driver how to access the user-mode data buffer, which is well understood;
Second, the second usage is that some drivers also use MDL when performing direct I/O to satisfy a device I/O control request, in the usual way as follows:
1, assign a buf, may be paged or non-paged;
2, call ioallocatemdl, point to this buf;
3, for paging memory, call Mmprobeandlockpages and Mmgetsystemaddressformdlsafe to lock the memory page to prevent the page out;
For non-paged memory, the call Mmbuildmdlfornonpagedpool is mapped to physical memory.
For the second usage, it may make sense for paging memory to ensure that it is not page out, but for non-paged memory, I think there is no use other than DMA, since it is already a non-paged memory, the direct use is good, why also generate an MDL to do the mapping. I have always been not very understanding, it is possible to understand the error, please advise ioallocatemdl
The ioallocatemdl function allocates enough to map a cache of MDL, given the starting address and length of the cache.
Pmdl
IOALLOCATEMDL (
__in_opt PVOID virtualaddress,
__in ULONG Length,
__in BOOLEAN SecondaryBuffer,
__in BOOLEAN Chargequota,
__inout_opt pirp Irp OPTIONAL
);
The driver can use the ioallocatemdl function for the purpose of large cache shards, mapping a small portion of the cache through a separate MDL, or mapping the memory that drives the allocations. The driver invokes Mmbuildmdlfornonpagedpool to set the MDL memory so that the MDL description Drive allocated cache is in non-replaceable memory.
The length parameter indicates the size of the cache that the MDL points to. In Windows Server 2003, Windows XP, and Windows 2000, the maximum number of cache bytes that can be allocated is page_size * (65535- sizeof(MDL))/ sizeof (ULONG_PTR). In Windows Vista and Windows Server 2008, the maximum number of cache bytes is (2gb-page_size). In Windows 7 and Windows Server R2, the maximum number of cache bytes is (4gb-page_size ).
If the SecondaryBuffer parameter is False, the function updates the irp->mdladdress to point to a new MDL, which means that it supports large cache shards. If SecondaryBuffer is true, this function adds the MDL to the chain that irp->mdladdress points to.
MDL (Memory Descriptor list)
Http://hi.baidu.com/reversefish/blog
typedef struct _MDL {
struct _MDL *next;
CSHORT Size;
CSHORT Mdlflags;
struct _eprocess *process;
PVOID Mappedsystemva;
PVOID Startva;
ULONG ByteCount;
ULONG Byteoffset;
} MDL, *pmdl;
The MDL is just a description of the physical memory, but because the system and driver use virtual memory, the MDL is "mapping" the virtual memory to physical memory (from DDK). This is very vague, in fact, the role of MDL is very simple: when driver to access a memory location, ensure that the memory location described by MDL does not cause page fault.
Gets the virtual memory location of the MDL. DDK specifically, Lower-level driver can not directly use this address, because it may be user-space memory location. Therefore, the driver must call Mmgetsystemaddressformdlsafe () to obtain and lock the memory location of the system-space to which this address corresponds.
If driver wants to establish an MDL that maps to driver's own configured non-paged memory, driver has to call Mmbuildmdlfornonpagedpool (). This is because IOALLOCATEMDL () only configures memory, but does not have a build MDL
Temporarily add a system space map to the user space buffer, which makes the same set of physical pages have two virtual address interval, one is the original user space virtual address interval, and the second is the virtual address range of the system space. Thus, the user space buffer can be accessed through the virtual address of the system space, and the mapping of the system space is not revoked until the operation is completed and the user space is returned. This method is called a "direct" method. Direct methods are not cost-effective for very small buffers, because the creation and revocation of temporary mappings requires some overhead and is appropriate for larger buffers.
1. User state to Kernel state
BASEADDR = OpenKernel32 (); Map the section of KERNEL32 to the low 2G space of this process
if (! BASEADDR)
{
Kdprint (("Driverentry--openkernel32 failure!\n"));
return 0;
}
Kdprint (("baseaddr:0x%08x\n", baseaddr));
Create an MDL
PMDL = IOALLOCATEMDL (baseaddr,0x11c000,false,false,null);
if (!PMDL)
{
Kdprint (("pmdl = = null\n"));
return 0;
}
_try
{
Mmprobeandlockpages (pmdl,usermode,ioreadaccess);
}
_except (Exception_execute_handler)
{
Kdprint (("Mmprobeandlockpages exception\n"));
}
_try
{
PMAPEDADDR = Mmmaplockedpagesspecifycache (pmdl,kernelmode,mmcached,null,false,normalpagepriority);
if (!PMAPEDADDR)
{
Kdprint (("Pmapedadd = = null\n"));
return 0;
}
}
_except (Exception_execute_handler)
{
Kdprint (("Mmmaplockedpagesspecifycache exception\n"));
}
2. Kernel state to User state
Psharemm_sys=exallocatepool (nonpagedpool,1024);//size must be an integer multiple of page
RtlZeroMemory (psharemm_sys,1024);
PSHAREMM_MDL=IOALLOCATEMDL (Psharemm_sys,1024,false,false,null);
Mmbuildmdlfornonpagedpool (PSHAREMM_MDL);
Psharemm_user=mmmaplockedpagesspecifycache (psharemm_mdl,usermode,mmcached,null,false,normalpagepriority);
Kdprint ("Psharemm_sys's address is: 0x%p\n", (Puchar) psharemm_sys));
Kdprint ("Psharemm_user's address is: 0x%p\n", (Puchar) psharemm_user));