注意:大多数低层磁盘和网络驱动通常不能使用可分页内存他们代码常常在较高IRQL等级执行而不允许页但是文件系统(通常比磁盘驱动占用更大更多资源)有时候可从可分页池中分配些内存非分页内存在整个系统中是个有限资源其数量依赖于系统使用类型和系统可用物理内存NT提供下面例程给内核驱动来分配内存:
ExAllocatePool
ExAllocatePoolWithQuota
ExAllocatePoolWithTag
ExAllocatePoolWithQuotaTag
这些来请求内存时必须要指定请求内存类型:
NonPagedPool 请求分配个不可分页内存
PagedPool 请求分配个可分页内存
如果你在分配内存里有任何同步结构话决不要分配分页内存当你应用访问内存时候可以处理页时候应该指定这个类型
NonPagedPoolMustSucceed
在其它方式都失败时而你又必须立即得到内存时候可以使用这个标志类型注意这种类型内存是极度缺乏资源可能不足16K注意只有在其它途径都失败时候才使用如果分配失败将会导致系统bugcheck代码是 MUST_SUCCEED_POOL_EMPTY
NonPagedPoolCacheAligned 这个标志分配使用数据缓存Cache线尺寸来在CPU特定边界对齐非分页内存注意这个操作默认是在Intel平台上 NonPagedPool 分配类型
PagedPoolCacheAligned 这个标志分配使用数据缓存Cache线尺寸来在CPU特定边界对齐分页内存
NonPagedPoolCacheAlignedMustSucceed
参考NonPagedPoolMustSucceed 和NonPagedPoolCacheAligned
内存池分配器化了些列表每个列表包含种固定大小块当你使用上面请求内存时例程试图分配个和你请求数量相近或更大点固定大小块但是如果你要求数量超过页时或者超过列表中最大块大小时又或者
在预先分配列表中没有可用块时候VMM就会从任何适当类型系统可用内存中分配你请求数量内存给你当预先分配列表空了时候VMM会分配至少页内存切分然后把剩下数据放进适当块列表中但是当你请求非分页内存数量超过PAGE_SIZE时候内存池分配例程不会切分未使用部分这会浪费宝贵非分页内存也可以使用 MmAllocateNonCachedMemory 或 MmAllocateContiguousMemory来分配非分页或物理连续内存它们通常不使用在文件系统或者过滤驱动中而是用于执行池例程或者其它结构内核驱动如果重复分配和释放小块内存(小于个PAGE_SIZE), 可能导致系统可用物理内存碎片化这会给系统带来各种问题包括降低系统性能等有个思路方法可以避免系统碎片化就是预先分配块合理大小内存然后自已管理在这个预先分配块中分配和释放小块内存但这种思路方法有可能会浪费核心内存
在ReactOS文件\ntoskrnl\mm\pool.c里看到下面代码:
#001 /*
#002 * @implemented
#003 */
#004 PVOID NTAPI
#005 ExAllocatePool (POOL_TYPE PoolType, ULONG NumberOfBytes)
#006 /*
#007 * FUNCTION: Allocates pool memory of a specied type and s a poer
#008 * to the allocated block. This routine is used for general purpose allocation
#009 * of memory
#010 * ARGUMENTS:
#011 * PoolType
#012 * Species the type of memory to allocate which can be one
#013 * of the following:
#014 *
#015 * NonPagedPool
#016 * NonPagedPoolMustSucceed
#017 * NonPagedPoolCacheAligned
#018 * NonPagedPoolCacheAlignedMustS
#019 * PagedPool
#020 * PagedPoolCacheAligned
#021 *
#022 * NumberOfBytes
#023 * Species the number of s to allocate
#024 * RETURNS: The allocated block on success
#025 * NULL on failure
#026 */
#027 {
#028 PVOID Block;
#029
#030 # d(__GNUC__)
#031
#032 Block = EiAllocatePool(PoolType,
#033 NumberOfBytes,
#034 TAG_NONE,
#035 (PVOID)__builtin__address(0));
#036 #el d(_MSC_VER)
#037
#038 Block = EiAllocatePool(PoolType,
#039 NumberOfBytes,
#040 TAG_NONE,
#041 &ExAllocatePool);
#042 #
#043 #error Unknown compiler
#044 #end
#045
#046 (Block);
#047 }
上面这个就是实现内核里分配分页内存和非分页内存下次再详细介绍如何样实现非分页内存
最新评论