MORE INFORMATION
IOCTL Method: Application Allocates Shared Memory
The easiest and best way to share memory between user mode and kernel mode
is to use device input and output controls (IOCTLs). Of the four different types, the following three IOCTLs enable you to access the user buffer directly in a device driver:
- METHOD_IN_DIRECT
- METHOD_OUT_DIRECT
- METHOD_NEITHER
No intermediate system buffer is created in any of these methods.
METHOD_IN_DIRECT and METHOD_OUT_DIRECT automatically lock the user-
specified buffer in
DeviceIoControl and create a memory descriptor list (MDL) for the driver. The driver can get a system address from the MDL and transfer information in and out of the buffer, depending on the IOCTL
transfer type. This is a simple, clean approach because all buffer
validation, locking, and MDL creation is done by the I/O manager.
In contrast, METHOD_NEITHER directly provides the user buffers to the
driver, and the driver must validate and lock the buffer appropriately and,
if needed, get a system address for the buffer. Even though this is the
fastest path through the I/O subsystem for a device driver, you must be cautious when you use this method.
For more information, see the following topic in the DDK:
Shared Memory Object Method
A memory-mapped file backed by the paging file is a common technique used
for sharing memory among user processes. However, you can use the same
technique to share memory between user processes and a device driver. There
are two approaches to this technique.
In the first method, a driver can create a named memory object (called a section object) and one or more user applications can open the same object by using
OpenFileMapping and then calling the
MapViewOfFile function to get a pointer to a section or all of the shared memory. By specifying protection attributes to the section object, you can define the manner in which a process can manipulate the memory.
In the second method, an application can create a named memory object in
user mode with
CreateFileMapping. A driver can open the same memory object by using
ZwOpenSection and calling
ZwMapViewOfSection to get a pointer to it. Always access this memory address in kernel mode with an exception handler.
Because the object is always mapped in the user address space (below
0x80000000) of a process (regardless of whether the object is created in
kernel mode or user mode) the address is valid only if it is accessed in
the context of the process. Every call to
MapViewOfFile or
to
ZwMapViewOfSection on the same memory object returns a different memory address even for the same process. This method is not recommended
and is used least by low-level device drivers because, as explained
earlier, the scope of the address is limited to the process in which the
object is mapped, and it cannot be accessed in a DPC or ISR. Also, the API
to create a memory object in kernel mode is not documented in the DDK.
However, to use the address at raised IRQL, such as in DPC or ISR, you have
to probe and lock the buffer pages and get a system virtual address
(MmGetSystemAddressForMdl) as described in the IOCTL method earliern in this article.
This method is simple and easy only if the memory is going to be shared
between two or more user processes and one or more device drivers.
Otherwise, it is much easier and more efficient to use the IOCTL technique
for sharing memory between a user process and a device driver.