Sharing Memory Between Drivers and Applications
2000 OSR Open Systems Resources, Inc.
Updated: 2002
At one time or another, most driver writers will have the need to share memory
between a driver and a user-mode program. And, as with most such things, there are a
wide variety of ways to accomplish the goal of sharing a block of memory between a
driver and a user-mode application. Some of these approaches are decidedly right and
some are wrong. Two of the easiest techniques are:
· The application sends an IOCTL to the driver, providing a pointer to a
buffer that the driver and the application thereafter share.
· The driver allocates a block of memory (from nonpaged pool for example),
maps that block of memory back in the address space of a specific user-
mode process, and returns the address to the application.
For the sake of brevity, we’ll restrict our discussion to these two, straightforward,
techniques. Other perfectly acceptable techniques include sharing a named section
that’s backed by either the paging file or a memory mapped file. Perhaps we’ll
discuss those in a future article. Also, note that this article won’t specifically address
sharing memory that’s resident on a device. While many of the concepts are the
same, sharing device memory with a user-mode program brings with it its own set of
special challenges.
Sharing Buffers Using IOCTLs
Sharing memory between a driver and a user-mode app using a buffer described with
an IOCTL is the simplest form of “memory sharing”. After all, it’s identical to the
way drivers support other, more typical, I/O requests. The base address and length of
the buffer to be shared are specified by the application in the OutBuffer of a call to the
Win32 function DeviceIoControl().
The only interesting decision for the driver writer who uses this method of buffer
sharing is which buffer method (or, “transfer type” as it’s known) to specify for the
IOCTL. Either METHOD_DIRECT (that is, using an MDL) or
METHOD_NEITHER (using user virtual addresses) will work. If
METHOD_DIRECT is used, the user buffer will be locked into memory. The driver
will also need to call MmGetSystemAddressForMdlSafe() to map the described
data buffer into kernel virtual address space. An advantage of this method is that the
driver can access the shared memory buffer from an arbitrary process context, and at
any IRQL.