Windows内存管理(2)--Lookaside结构 和 运行时函数

1.      Lookaside结构

频繁的申请和回收内存,会导致在内存上产生大量的内存“空洞”,从而导致最终无法申请内存。DDK为程序员提供了Lookaside结构来解决这个问题。

我们可以将Lookaside对象看成是一个内存容器。在初始化的时候,它先向Windows申请了一块比较大的内存。以后程序员每次申请内存的时候,不是直接向Windows申请内存,而是想Lookaside对象申请内存。Looaside会智能的避免产生内存“空洞”。如果Lookaside对象内部内存不够用时,它会向操作系统申请更多的内存。

Lookaside一般会在以下情况下使用:

1.       程序员每次申请固定大小的内存。

2.       申请和回收的操作十分频繁。

要使用Looaside对象,首先要初始化Lookaside对象,有以下两个函数可以使用:

1VOID
  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对象后,可以进行申请内存的操作了:

1PVOID
    ExAllocateFromNPagedLookasideList(
    IN PNPAGED_LOOKASIDE_LIST
  Lookaside
    );

2PVOID
  ExAllocateFromPagedLookasideList(
    IN PPAGED_LOOKASIDE_LIST
  Lookaside
    );

Lookaside对象回收内存:

1VOID
  ExFreeToNPagedLookasideList(
    IN PNPAGED_LOOKASIDE_LIST
  Lookaside,
    IN PVOID
  Entry
    )

2VOID
  ExFreeToPagedLookasideList(
    IN PPAGED_LOOKASIDE_LIST
  Lookaside,
    IN PVOID
  Entry
    );

在使用完Lookaside对象后,要删除Lookaside对象:

1VOID
  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 (int i=0; i<50; i++)

     {

         pMyData[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&Lookaside);

         if ((i+1)%10 == 0)

         {

 

              KdPrint(("申请了 %d 个数据了!\n", ++i));

         }

     }

     for (int i=0; i<50; i++)

     {

         ExFreeToPagedLookasideList(&Lookaside, pMyData[i]);

         pMyData[i] = NULL;

         if ((i+1)%10 == 0)

         {

              KdPrint(("释放了 %d 个数据的内存了!\n", ++i));

         }

     }

     ExDeletePagedLookasideList(&Lookaside);

}


 

2.运行时函数

(1)内存间复制(非重叠)

VOID
  RtlCopyMemory(
    IN VOID UNALIGNED  *
Destination,
    IN CONST VOID UNALIGNED  *
Source,
    IN SIZE_T
  Length
    );

(2)内存间复制(可重叠)

VOID
  RtlMoveMemory(
    IN VOID UNALIGNED
  *Destination,
    IN CONST VOID UNALIGNED  *
Source,
    IN SIZE_T
  Length
    );

3)填充内存

VOID
  RtlFillMemory(
    IN VOID UNALIGNED
  *Destination,
    IN SIZE_T
  Length,
    IN UCHAR
  Fill
    );

VOID
  RtlZeroMemory(
    IN VOID UNALIGNED
  *Destination,
    IN SIZE_T
  Length
    );

4)内存比较

SIZE_T
  RtlCompareMemory(
    IN CONST VOID
  *Source1,
    IN CONST VOID
  *Source2,
    IN SIZE_T
  Length
    );

ULONG
  RtlEqualMemory(
    CONST VOID  *
Source1,
    CONST VOID  *
Source2,
    SIZE_T
  Length
    );

#define BUFFER_SIZE 1024

#pragma INITCODE

VOID RtlTest()

{

     KdPrint(("进入RtlTest函数!\n"));

     PUCHAR pBuffer1 = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);

     RtlZeroMemory(pBuffer1, BUFFER_SIZE);

     PUCHAR pBuffer2 = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);

     RtlFillMemory(pBuffer2, BUFFER_SIZE, 0xAA);

     RtlCopyMemory(pBuffer1, pBuffer2, BUFFER_SIZE);

     

     if (RtlEqualMemory(pBuffer1, pBuffer2, BUFFER_SIZE))

     {

         KdPrint(("两块内存块数据一样!\n"));

         for(int i=0; i<BUFFER_SIZE; i++)

         {

              KdPrint(("%02X", pBuffer1[i]));

         }

         

     }

     else

     {

         KdPrint(("两块内存块数据不一样!\n"));

     }

     KdPrint(("离开RtlTest函数!\n"));

}


 

你可能感兴趣的:(Windows内存管理(2)--Lookaside结构 和 运行时函数)