Parameter Description
IN POOL_TYPE PoolType PagedPool PagePoolCacheAligned NonPagedPool NonPagedPoolMustSucceed NonPagedPoolCacheAligned NonPagedPoolCacheAlignedMustS
IN ULONG NumberOfBytes Number of bytes to allocate
Returns Pointer to allocated memory or NULL
Lookaside Lists

If your driver keeps on allocating and deallocating small amounts of pool memory then it will be inefficient and the available heap will fragment. The kernel helps in this case by providing lookaside lists[6] for fixed-size chunks of memory. A lookaside list still gets memory from the pool. However, when you free a chunk of memory, it is not necessarily returned to the pool. Instead, some chunks are kept in the lookaside list, ready to satisfy the next allocation request. The number of chunks kept is determined by the kernel memory manager.

Lookaside lists can contain either paged or nonpaged memory. Use ExInitializeNPagedLookasideList to initialize a lookaside list for nonpaged memory and ExDeleteNPaged-LookasideList to delete the lookaside list. When you want to allocate a chunk of memory, call ExAliocateFromNPagedLookasideList. To free a chunk, call ExFreeToNPaged-LookasideList. A similar set of functions is used for paged memory. Consult the DDK for full details of these functions.

Other Memory Considerations

The kernel stack is nonpaged memory for local variables[7]. There is not room for huge data structures on the kernel stack because it is only 8KB-12KB long.

Drivers need to be reentrant, so they can be called simultaneously on different processors. The use of global variables is, therefore, strongly discouraged. However, you might read in some registry settings into globals, as they are effectively constant for all the code. Local static variables should also not normally be used for the same reason.

Finally, you can reduce your driver's memory usage in other ways. Once the driver initialization routines have completed, they will not be needed again, so they can be discarded. Similarly, some routines may be put into a pageable code segment. However, routines running at DISPATCH_LEVEL or above need to be in nonpageable nondiscardable memory.

Accessing User Application Memory

There are two main techniques for accessing user data buffers. If you use Buffered I/O, the I/O Manager lets you use a nonpaged buffer visible in system memory for I/O operations. The I/O Manager copies write data into this buffer before your driver is run, and copies back read data into user space when the request has completed.

The alternative technique, Direct I/O, is preferable, as it involves less copying of data. However, it is slightly harder to use and is usually only used by DMA drivers that transfer large amounts of data. The I/O Manager passes a Memory Descriptor List (MDL) that describes the user space buffer. While a driver can make the user buffer visible in the system address space, the MDL is usually passed to the DMA handling kernel routines.

DMA

Direct Memory Access (DMA) hardware controllers perform I/O data transfers direct from a device to main memory (or vice versa) without going through the processor. The first implication is that DMA memory cannot be paged. Secondly, the DMA controller has to be programmed with a physical memory address, not a processor virtual address. The kernel provides routines to help with both these tasks.

IRP Processing

I/O Request Packets (IRPs) are central to the operation of drivers. It is helpful to look at them briefly at this point, but they are described in full later. In particular, this section looks at how IRP parameters are stored and how the IRP stack lets an irp be processed by a stack of drivers.

An IRP is a kernel 'object', a predefined data structure with a set of I/O Manager routines that operate on it. The I/O Manager receives an I/O request and then allocates and initializes an IRP before passing it to the highest driver in the appropriate driver stack.

An IRP has a fixed header part and a variable number of IRP stack location blocks, as shown in Figure 3.1. Each I/O request has a major function code (such as IRP_MJ_CREATE corresponding to a file open) and possibly a minor function code. For example, the IRP_MJ_PNP Plug and Play IRP has several minor functions (e.g., IRP_MN_START_DEVICE). Table 3.5 lists the common IRP major function codes.

Table 3.5 Common IRP Major Function Codes

IRP_MJ_CREATE Create or open device file
IRP_MJ_CLOSE Close handle
IRP_MJ_READ Read
IRP_MJ_WRITE Write
IRP_MJ_CLEANUP Cancel any pending IRPs on a file handle
IRP_MJ_DEVICE_CONTROL Device I/O control
IRP_MJ_INTERNAL_DEVICE_CONTROL This is also called IRP_MJ_SCSI Device I/O control from a higher driver
IRP_MJ_SYSTEM_CONTROL Windows Management Instrumentation
IRP_MJ_POWER Power Management request
IRP_MJ_PNP Plug and Play message
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×