What is a MDL?
This definition is available in msdn.
The memory descriptor list (MDL) is a system-defined structure that describes the buffer zone through a series of physical addresses. Execute direct I/O DriverProgramReceives an MDL pointer from the I/O manager and reads and writes data through the MDL. Some drivers also use MDL when executing direct I/O to meet device I/O control requests.
BytesArticleIt was translated by robots, so it seems a little headache.
As a general explanation, MDL is only used in the kernel and does not involve this structure at the application layer. Because the driver in the kernel needs to communicate with the application layer program, therefore, the virtual address from the process space may be received, while in the paging mechanism of windows, the page of any virtual address in the process space may be replaced by the Memory Manager from raw to the page file, or the process is released or the address ing is canceled. These will cause serious errors. Therefore, the kernel creates an MDL and associates it with virtual addresses from the process space. When you need to read and write these virtual addresses, it calls the relevant kernel functions, lock the physical and logical pages corresponding to these virtual addresses to prevent physical pages from being replaced and logical pages from being modified or released.
In another case, the driver can also use MDL to execute pure kernel tasks. In particular, if only non-Paging memory is called, these pages will not be replaced in the page file, therefore, you do not need to consider locking the page.
2. MDL content
Let's take a look at the MDL definition in WDM. h:
Typedef _ struct_bcount (size) struct _ MDL {
Struct _ MDL * next;
Cshort size;
Cshort mdlflags;
Struct _ eprocess * process;
Pvoid mappedsystemva;
Pvoid startva;
Ulong bytecount;
Ulong byteoffset;
} MDL, * pmdl;
Briefly describe the fields of love:
Next: MDL can be connected to a single-chain table, so scattered virtual machine addresses can be connected in a string.
Size: An MDL does not only contain these items in the structure. In the memory, an MDL structure is followed by the physical page numbers corresponding to this MDL. Since a physical page must be 4 kb aligned, therefore, this number is equivalent to 20 characters in height of the starting address of a physical page. The value of size minus sizeof (MDL) is equal to the size of the region where the number is stored. For example, if the MDL requires three physical pages to map the virtual address space, size-sizeof (MDL) = 4*3 = 12;
Mdlflags: an important field used to describe and manipulate various attributes of a virtual address.
Process: If the virtual address is the user address space of a process, the virtual address represented by MDL must belong to a process, and the member points to the structure of the subordinate process.
Mappedsystemva: The physical page corresponding to the MDL structure may be mapped to the kernel address space. This member represents the virtual address in the kernel address space. The inverse of mmbuildmdlfornonpagedpool indicates that mappedsystemva = startva + byteoffset. This is because the input MDL of this function and its startva are determined by exallocatepoolwithtag. Therefore, the ing has been established from the kernel space to the physical page, and mappedsystemva can be calculated as such. It can be guessed that if it is calledMMP robeandlockpages
If this parameter is returned, mappedsystemva does not correspond to startva because the corresponding physical page is not mapped to the kernel space. (Not fixed here,MMP robeandlockpagesWhether to establish a PDE ing with the Pte. It is unknown .)
Startva: the first address of the virtual address space. When this virtual address describes a part of the user process address space, this address belongs to a specific process.
Bytecount: size of the virtual address block, in bytes
Byteoffset: startva + bytecount is equal to the starting address of the buffer.
Since the wdk document is vague, some of the above descriptions are just guesses. We can use dbg to debug a driver and observe its original memory data to confirm our speculation.
Below is a section from tdifwCodeIt allocates a non-Paging memory block for an IPv4 address CTX-> Tai, and then calls ioallocatemdl to create an MDL for this virtual address, finally, mmbuildmdlfornonpagedpool is called to establish direct ing between virtual addresses and physical pages.
CTX-> Tai = (tdi_address_info *) malloc_np (tdi_address_info_max );
If (CTX-> Tai = NULL ){
Kdprint ("[tdi_fw] tdi_create_addrobj_complete: malloc_np! \ N "));
Status = status_insufficient_resources;
Goto done;
}
We can see that the first Tai address is 0x82040928, which is a virtual address in non-Paging memory and the length is 0x55.
MDL = ioallocatemdl (CTX-> Tai, tdi_address_info_max, false, false, null );
If (MDL = NULL ){
Kdprint ("[tdi_fw] tdi_create_addrobj_complete: ioallocatemdl! \ N "));
Status = status_insufficient_resources;
Goto done;
}
Memory allocated after MDL:
The first address of MDL is 0x82010210, And the size is 32. This is the size of the MDL structure. The value of mdlflags is 8, and the value of mappedsystemva is 0xf8c9oa9c.
Startva is 0x82040000, indicating that startva currently represents the starting page address of the virtual address pointed to by Tai, and bytecount is 55, which indicates the size of the virtual address, byteoffset is 0x929, so this byte represents the offset of the virtual address to the page.
Mmbuildmdlfornonpagedpool (MDL );
After calling this function:
Only three fields have changed.
Mdlflags is changed to 12, mappedsystemva actually points to the virtual address, and process is set to 0, indicating that this is a non-Paging address, which does not belong to the address space of any process.
In fact, the size is not equal to the size of the MDL structure, because the MDL is followed by an array representing the physical page, but it is not displayed in the structure, this should be done to prevent general drivers from directly modifying these physical arrays, because the ing between virtual addresses and physical pages should only be maintained by the Memory Manager. In the debugging just now, observe the memory and find that there is only one physical page number behind the MDL. This number is not initialized when ioallocatemdl is called, but is assigned in mmbuildmdlfornonpagedpool (MDL. Some people think that mmbuildmdlfornonpagedpool maps physical pages to the system address space. This statement should be incorrect, because for non-Paging memory, when calling the exallocatepool series functions, the memory manager establishes a ing relationship, otherwise the memory cannot be used at all. In fact, the role of mmbuildmdlfornonpagedpool is to save the ing to MDL and make it opaque, in order to meet certain driver requirements, the article should not be too long, and the next article will continue to analyze.