A memory descriptor list (MDL) describes a
list of pages in physical memory. Internally, the Windows kernel uses MDLs in
numerous ways. For example, when the I/O manager sets up a direct I/O request
to send to a driver, it creates an MDL to describe the I/O buffer. The driver
receives a pointer to the MDL in the request at Irp->MdlAddress.
When the driver receives the request, the
pages described by the MDL have already been locked into memory by the creator
of the MDL. To use virtual addresses to access the buffer described by the MDL,
the driver calls MmGetSystemAddressForMdlSafe
to map the buffer into system space. This function returns a valid system-space
virtual address that the driver can use to access the buffer.
Drivers create MDLs in the following
situations:
·
The driver receives an I/O
request for neither buffered nor direct (METHOD_NEITHER) I/O.
·
The driver initiates an I/O
request to send to another driver.
·
The driver splits a large I/O
buffer into two or more smaller buffers.
·
The driver allocates physical
memory from a specific physical address range.
When a driver receives a request for METHOD_NEITHER
I/O, a pointer to a buffer is part of the request. If the originator of the I/O
request is another kernel-mode component, the buffer can be in system space.
More often, however, the originator of the request is a user-mode process, so
the buffer is in user space. To read and write to this user-space buffer, the
driver must create an MDL that describes these pages and must ensure that they
remain accessible until the driver has completed the I/O request. Creating the MDL
locks the pages into memory so that any subsequent access is guaranteed to be
protected. If the driver must use virtual addresses to access the pages
described by the MDL, it must map those pages into the system address space
using MmGetSystemAddressForMdlSafe.
This function returns a valid system-space virtual address with which the
driver can safely access the buffer.
When a driver initiates an I/O request,
it allocates an MDL to describe the buffer in the I/O request. For example, a
driver might send a device I/O control request (IRP_MJ_INTERNAL_DEVICE_CONTROL)
to a lower driver in its stack to request some kind of intervention with the
hardware. The driver would call IoAllocateMdl
to create an MDL and later use a different system function to fill in the MDL,
depending on the type of request. If the request specifies direct I/O, the
lower driver would receive a pointer to the MDL in the request at Irp‑>MdlAddress.
To split a large I/O buffer into smaller
buffers, a driver might also use an MDL. Typically, splitting a buffer in this
way is required only during direct I/O operations, if the supplied buffer is
too large for the device or if the driver or device can operate more
efficiently with several smaller buffers. To split a buffer, the driver calls IoAllocateMdl to create the new MDL, and
then calls IoBuildPartialMdl to map
a subset of the range described by the original MDL into the new one.
A driver that allocates physical memory
from a specific range of addresses must also create an MDL to describe the
allocated memory. In this case, the driver calls MmAllocatePagesForMdl (which allocates the memory), creates the MDL,
and locks the pages. If the driver requires access to the pages through virtual
addresses, the driver also calls MmGetSystemAddressForMdlSafe
to map the pages into virtual memory and return a virtual address for the
driver’s use.
Table 2 summarizes Windows routines that
create and manipulate MDLs.
Table 2. Summary of MDL Routines
Name
|
Description
|
MmAllocateMappingAddress
|
Reserves a range
of virtual addresses for mapping, but does not actually map them to physical
memory.
To map the
virtual addresses in the reserved range to physical addresses, the driver
later calls IoAllocateMdl, MmProbeAndLockPages, and MmMapLockedPagesWithReservedMapping. This
technique is less efficient than calling MmGetSystemAddressForMdlSafe
or MmMapLockedPagesXxx, but is useful because it
allows driver execution to continue in situations when calling these latter
functions fails.
|
IoAllocateMdl
|
Allocates an MDL
for a buffer, given the starting virtual address of the buffer and its
length.
This routine
does not associate the physical pages in the buffer with the allocated MDL. To
do so, the driver must call MmBuildMdlForNonPagedPool,
IoBuildPartialMdl, or MmProbeAndLockPages.
|
MmProbeAndLockPages
|
Confirms that
the pages described by an MDL permit the requested type of access and, if so,
locks those pages into memory.
|
MmBuildMdlForNonPagedPool
|
Fills in an MDL
to describe a buffer that is allocated in system-space memory from the
nonpaged pool. The MDL must have been allocated by IoAllocateMdl.
A driver can
also use this function on I/O space, typically by mapping the space with MmMapIoSpace and then passing the
returned virtual address to MmBuildMdlForNonPagedPool.
|
MmAllocatePagesForMdl
|
Allocates
nonpaged, noncontiguous pages from physical memory, specifically for an MDL. A
driver calls this function to allocate physical memory from a particular
address range. Do not use this function to allocate memory for DMA; use the
system’s DMA routines instead.
This function
might return fewer pages than the caller requested. Therefore, the driver
must call MmGetMdlByteCount to verify
the number of bytes allocated.
|
MmGetSystemAddressForMdlSafe
|
Maps the
physical pages described by an MDL into system space and returns a virtual
address for the MDL.
The returned virtual
address can be used at any IRQL and in any process context.
|
IoBuildPartialMdl
|
Maps part of a
buffer described by an existing MDL into a new MDL that the driver previously
allocated by calling IoAllocateMdl.
|
MmAdvanceMdl
|
Increases the
starting address of an MDL.
A driver calls
this function to update the MDL to describe a partial buffer when I/O
operations are not (or cannot be) completed, either because not enough memory
is available or because the device can write only part of the buffer at a
time.
|
MmGetMdlVirtualAddress
|
Returns the
starting virtual address of an MDL.
|
IoFreeMdl
|
Frees an MDL that was previously allocated by IoAllocateMdl.
|
MmFreePagesFromMdl
|
Frees the pages described by an MDL that was previously created by MmAllocatePagesForMdl.
|
0 komentar:
Posting Komentar