[Windows驱动开发]内存管理
Posted 狂客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Windows驱动开发]内存管理相关的知识,希望对你有一定的参考价值。
- //
- #define PAGEDCODE code_seg("PAGE")
- #define LOCKEDCODE code_seg()
- #define INITCODE code_seg("INIT")
- #define PAGEDDATA code_seg("PAGE")
- #define LOCKEDDATA code_seg()
- #define INITDATA code_seg("INIT")
- //
// #define PAGEDCODE code_seg("PAGE") #define LOCKEDCODE code_seg() #define INITCODE code_seg("INIT") #define PAGEDDATA code_seg("PAGE") #define LOCKEDDATA code_seg() #define INITDATA code_seg("INIT") //
- //
- #pragma PAGEDCODE
- VOID SomeFunction()
- {
- PAGED_CODE();
- // Do any other things ....
- }
- //
// #pragma PAGEDCODE VOID SomeFunction() { PAGED_CODE(); // Do any other things .... } //
- //
- #pragma LOCKEDCODE
- VOID SomeFunction()
- {
- // Do any other things ....
- }
- //
// #pragma LOCKEDCODE VOID SomeFunction() { // Do any other things .... } //
- //
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
- {
- // Do any other things ....
- }
- //
// #pragma INITCODE extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) { // Do any other things .... } //
- //
- NTKERNELAPI
- PVOID
- ExAllocatePool(
- __drv_strictTypeMatch(__drv_typeExpr) __in POOL_TYPE PoolType,
- __in SIZE_T NumberOfBytes
- );
- NTKERNELAPI
- PVOID
- NTAPI
- ExAllocatePoolWithTag(
- __in __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType,
- __in SIZE_T NumberOfBytes,
- __in ULONG Tag
- );
- NTKERNELAPI
- PVOID
- ExAllocatePoolWithQuota(
- __drv_strictTypeMatch(__drv_typeExpr) __in POOL_TYPE PoolType,
- __in SIZE_T NumberOfBytes
- );
- NTKERNELAPI
- PVOID
- ExAllocatePoolWithQuotaTag(
- __in __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType,
- __in SIZE_T NumberOfBytes,
- __in ULONG Tag
- );
- //
// NTKERNELAPI PVOID ExAllocatePool( __drv_strictTypeMatch(__drv_typeExpr) __in POOL_TYPE PoolType, __in SIZE_T NumberOfBytes ); NTKERNELAPI PVOID NTAPI ExAllocatePoolWithTag( __in __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType, __in SIZE_T NumberOfBytes, __in ULONG Tag ); NTKERNELAPI PVOID ExAllocatePoolWithQuota( __drv_strictTypeMatch(__drv_typeExpr) __in POOL_TYPE PoolType, __in SIZE_T NumberOfBytes ); NTKERNELAPI PVOID ExAllocatePoolWithQuotaTag( __in __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType, __in SIZE_T NumberOfBytes, __in ULONG Tag ); //
- //
- NTKERNELAPI
- VOID
- ExFreePoolWithTag(
- __in __drv_freesMem(Mem) PVOID P, // 要释放的地址
- __in ULONG Tag
- );
- #define ExFreePool(a) ExFreePoolWithTag(a,0)
- //
// NTKERNELAPI VOID ExFreePoolWithTag( __in __drv_freesMem(Mem) PVOID P, // 要释放的地址 __in ULONG Tag ); #define ExFreePool(a) ExFreePoolWithTag(a,0) //
- // WDK中定义的双向链表数据结构
- //
- // Doubly linked list structure. Can be used as either a list head, or
- // as link words.
- //
- typedef struct _LIST_ENTRY {
- struct _LIST_ENTRY *Flink;
- struct _LIST_ENTRY *Blink;
- } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
- //
- // Singly linked list structure. Can be used as either a list head, or
- // as link words.
- //
- typedef struct _SINGLE_LIST_ENTRY {
- struct _SINGLE_LIST_ENTRY *Next;
- } SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
- //
// WDK中定义的双向链表数据结构 // // Doubly linked list structure. Can be used as either a list head, or // as link words. // typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; // // Singly linked list structure. Can be used as either a list head, or // as link words. // typedef struct _SINGLE_LIST_ENTRY { struct _SINGLE_LIST_ENTRY *Next; } SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; //
- //
- typedef struct _MYDATASTRUCT{
- // List Entry要作为_MYDATASTRUCT结构体的一部分
- LIST_ENTRY ListEntry;
- // 自己定义的数据
- ULONG x;
- ULONG y;
- };
- //
// typedef struct _MYDATASTRUCT{ // List Entry要作为_MYDATASTRUCT结构体的一部分 LIST_ENTRY ListEntry; // 自己定义的数据 ULONG x; ULONG y; }; //
- //
- InsertHeadList(&head, &mydata->ListEntry);
- //
// InsertHeadList(&head, &mydata->ListEntry); //
- //
- InsertTailList(&head, &mydata->ListEntry);
- //
// InsertTailList(&head, &mydata->ListEntry); //
- //
- PLIST_ENTRY pEntry = RemoveHeadList(&head);
- PLIST_ENTRY pEntry = RemoveTailList(&tail);
- //
// PLIST_ENTRY pEntry = RemoveHeadList(&head); PLIST_ENTRY pEntry = RemoveTailList(&tail); //
- //
- PLIST_ENTRY pEntry = RemoveHeadList(&head);
- PIRP pIrp = CONTAINING_RECORD(pEntry, MYDATASTRUCT, ListEntry);
- //
// PLIST_ENTRY pEntry = RemoveHeadList(&head); PIRP pIrp = CONTAINING_RECORD(pEntry, MYDATASTRUCT, ListEntry); //
三、 Lookaside结构
- // WDK提供的Lookaside初始化函数
- VOID ExInitializeNPagedLookasideList(
- IN PNPAGED_LOOKASIDE_LIST Lookaside,
- IN PALLOCATE_FUNCTION Allocate OPTIONAL,
- IN PFREE_FUNCTION Free OPTIONAL,
- IN ULONG Flags,
- IN SIZE_T Size,
- IN ULONG Tag,
- IN USHORT Depth);
- VOID ExInitializePagedLookasideList(
- IN PPAGED_LOOKASIDE_LIST Lookaside,
- IN PALLOCATE_FUNCTION Allocate OPTIONAL,
- IN PFREE_FUNCTION Free OPTIONAL,
- IN ULONG Flags,
- IN SIZE_T Size,
- IN ULONG Tag,
- IN USHORT Depth);
- //
// WDK提供的Lookaside初始化函数 VOID ExInitializeNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth); VOID ExInitializePagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth); //
- //
- VOID
- ExFreeToNPagedLookasideList(
- IN PNPAGED_LOOKASIDE_LIST Lookaside,
- IN PVOID Entry);
- VOID
- ExFreeToPagedLookasideList(
- IN PPAGED_LOOKASIDE_LIST Lookaside,
- IN PVOID Entry);
- //
// VOID ExFreeToNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry); VOID ExFreeToPagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry); //
- //
- VOID ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside);
- VOID ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside);
- //
// VOID ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside); VOID ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside); //
Lookaside结构
频繁的申请和回收内存,会导致在内存上产生大量的内存“空洞”,从而导致最终无法申请内存。DDK为程序员提供了Lookaside结构来解决这个问题。
我们可以将Lookaside对象看成是一个内存容器。在初始化的时候,它先向Windows申请了一块比较大的内存。以后程序员每次申请内存的时候,不是直接向Windows申请内存,而是想Lookaside对象申请内存。Looaside会智能的避免产生内存“空洞”。如果Lookaside对象内部内存不够用时,它会向操作系统申请更多的内存。
Lookaside一般会在以下情况下使用:
1. 程序员每次申请固定大小的内存。
2. 申请和回收的操作十分频繁。
要使用Looaside对象,首先要初始化Lookaside对象,有以下两个函数可以使用:
(1)VOID ExInitializeNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth );
(2)VOID ExInitializePagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth );
初始化玩Lookaside对象后,可以进行申请内存的操作了:
(1)PVOID ExAllocateFromNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside );
(2)PVOID ExAllocateFromPagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside );
对Lookaside对象回收内存:
(1)VOID ExFreeToNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry );
(2)VOID ExFreeToPagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry );
在使用完Lookaside对象后,要删除Lookaside对象:
(1)VOID ExDeleteNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside );
(2) VOID ExDeletePagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside );
测试代码:
#pragma INITCODE
VOID LookasideTets()
{
KdPrint(("进入LookasideTest函数!\n"));
PAGED_LOOKASIDE_LIST Lookaside;
ExInitializePagedLookasideList(&Lookaside,NULL, NULL, 0, sizeof(MYDATASTRUCT), ‘abcd‘, 0);
PMYDATASTRUCT pMyData[50];
for (inti=0; i<50; i++)
{
pMyData[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&Lookaside);
if ((i+1)%10 == 0)
{
KdPrint(("申请了 %d 个数据了!\n", ++i));
}
}
for (inti=0; i<50; i++)
{
ExFreeToPagedLookasideList(&Lookaside,pMyData[i]);
pMyData[i] =NULL;
if ((i+1)%10 == 0)
&nbs
以上是关于[Windows驱动开发]内存管理的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Windows 驱动程序(又名内核空间)确定 CPU 和内存消耗