Windows内核编程之:内存管理

分配内核函数

/************************************************************************

* 函数名称:ExAllocatePool

* 功能描述:分配内核内存

* 参数列表:

      PoolType:是个枚举变量

            NonPagedPool:分配非分页内存

            PagedPool:分配分页内存            

            NonPagedPoolMustSucceed:指定分配非分页内存,必须成功

            DontUseThisType:未指定

            NonPagedPoolCacheAligned:指定要求分配非分页内存,而且必须内存对齐

            PagedPoolCacheAligned:指定分配分页内存,而且必须内存对齐

            NonPagedPoolCacheAlignedMustS:指定分配非分页内存,而且必须内存对齐,而且必须成功

      NumberOfBytes:分配内存的大小,最好是4的倍数

      Tag:系统在要求的内存外又额外地多分配了4个字节的标签

      在调试的时候,可以找出是否有标有这个标签的内存没有被释放

* 返回 值:

        返回分配的内存地址,一定是内核模式地址

        如果为0,则代表分配失败



四个函数的功能类似

函数以WithQuota结尾的代表分配的时候按配额分配

函数以WithTag结尾的函数,和ExAllocatePool功能类似

*************************************************************************/

PVOID ExAllocatePool(

    IN POOL_TYPE PoolType,

    IN SIZE_T NumberOfBytes);

PVOID ExAllocatePoolWithTag(

    IN POOL_TYPE PoolType,

    IN SIZE_T NumberOfBytes,

    IN ULONG Tag);

PVOID ExAllocatePoolWithQuota(

    IN POOL_TYPE PoolType,

    IN SIZE_T NumberOfBytes);

PVOID ExAllocatePoolWithQuotaTag(

    IN POOL_TYPE PoolType,

    IN SIZE_T NumberOfBytes,

    IN ULONG Tag);

释放内存

VOID ExFreePool(

    IN PVOID p);

NTKERNELAPI VOID ExFreePoolWithTag(

    IN PVOID p,

    IN ULONG Tag);

 

Lookaside结构

  1. 频繁的申请和回收内存,会导致在内存上产生大量的内存“空洞”,从而导致最终无法申请内存。DDK为程序员提供了Lookaside结构来解决这个问题。
  2. 我们可以将Lookaside对象看成是一个内存容器。在初始化的时候,它先向Windows申请了一块比较大的内存。以后程序员每次申请内存的时候,不是直接向Windows申请内存,而是想Lookaside对象申请内存。Looaside会智能的避免产生内存“空洞”。如果Lookaside对象内部内存不够用时,它会向操作系统申请更多的内存。

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

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

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

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

//这两个函数分别是对非分页和分页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 ExInitalizePagedLookasideList(

    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);



//这两个函数分别是对非分页内存和分页内存的申请

PVOID ExAllocateFromNpagedLookasideList(

    IN PNPAGED_LOOKASIDE_LIST Lookaside);



PVOID ExAllocateFromPagedLookasideList(

    IN PPAGED_LOOKASIDE_LIST Lookaside);



//这两个函数分别是对非分页内存和分页内存的回收

VOID ExFreeToNPagedLookasideList(

    IN PNPAGED_LOOKASIDE_LIST Lookaside,

    IN PVOID Entry);



VOID ExFreeToPagedLookasideList(

    IN PPAGED_LOOKASIDE_LIST Lookaside,

    IN PVOID Entry);



//这两个函数分别是对非分页和分页Lookaside对象的删除

VOID ExDeleteNPagedLookasideList(

    IN PNPAGED_LOOKASIDE_LIST Lookaside);



VOID ExDeletePagedLookasideList(

    IN PPAGED_LOOKASIDE_LIST Lookaside);
/************************************************************************

* 函数名称:LookasideTest

* 功能描述:利用Lookaside对象频繁地申请和回收内存

* 参数列表:

* 返回 值:VOID

*************************************************************************/

#pragma INITCODE

VOID LookasideTest()

{

    //初始化Lookaside对象

    PAGED_LOOKASIDE_LIST pageList;

    ExInitializePagedLookasideList(

        &pageList,

        NULL,

        NULL,

        0,

        sizeof(MYDATASTRUCT),

        '1234',

        0);

    #define ARRAY_NUMBER 50

    PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER];

    //模拟频繁申请内存

    int i;

    for (i=0; i<ARRAY_NUMBER; i++)

    {

        MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList);

    }



    //模拟频繁回收内存

    for(i=0; i<ARRAY_NUMBER; i++)

    {

        ExFreeToPagedLookasideList(&pageList, MyObjectArray[i]);

        MyObjectArray[i] = NULL;

    }

    //删除Lookaside对象

    ExDeletePagedLookasideList(&pageList);

}

 

内存间复制

/************************************************************************

* 函数名称:RtlCopyMemory

* 功能描述:内存间复制(非重叠)

* 参数列表:

        Destination:表示要复制内存的目的地址

        Source:表示要复制内存的源地址

        Length:表示要复制内存的长度,单位是字节

* 返回 值:VOID

*************************************************************************/

VOID RtlCopyMemory(

    IN VOID UNALIGNED *Destination,

    IN CONST VOID UNALIGNED *Source,

    IN SIZE_T Length);



/************************************************************************

* 函数名称:RtlMoveMemory

* 功能描述:内存间复制(可重叠)

* 参数列表:

        Destination:表示要复制内存的目的地址

        Source:表示要复制内存的源地址

        Length:表示要复制内存的长度,单位是字节

* 返回 值:VOID

*************************************************************************/

VOID RtlMoveMemory(

    IN VOID UNALIGNED *Destination,

    IN CONST VOID UNALIGNED *Source,

    IN SIZE_T Length);

 

填充内存

/************************************************************************

* 函数名称:RtlFillMemory

* 功能描述:内存填充

* 参数列表:

        Destination:目的地址

        Length:长度

        Fill:需要填充的字节

* 返回 值:VOID

*************************************************************************/

VOID RtlFillMemory(

    IN VOID UNALIGNED *Destination,

    IN SIZE_T Length,

    IN UCHAR Fill);



#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length))



/************************************************************************

* 函数名称:RtlZeroMemory

* 功能描述:对某段内存填零

* 参数列表:

        Destination:目的地址

        Length:长度

* 返回 值:VOID

*************************************************************************/

VOID RtlZeroMemory(

    IN VOID UNALIGNED *Destination,

    IN SIZE_T Length);



#define RrlZeroMemory(Destination, Length) memset((Destination), 0, (Length))

 

 内存比较

/************************************************************************

* 函数名称:RtlZeroMemory

* 功能描述:内存比较

* 参数列表:

        Source1:比较的第一个内存地址

        Source2:比较的第二个内存地址

        Length:比较的长度,单位为字节

* 返回 值:相等的字节数

        不一致返回零        

*************************************************************************/

ULONG RtlEqualMemory(

    CONST VOID *Source1,

    CONST VOID *Source2,

    SIZE_T Length);



#define RtlEqualMemory(Destination, Source, Length) (!memcmp((Destination), (Source), (Length)))

 

检验内存间赋值、填充内存、内存比较
/************************************************************************

* 函数名称:RtlTest

* 功能描述:检验内存间赋值、填充内存、内存比较

* 参数列表:

* 返回 值:VOID

*************************************************************************/

#define BUFFER_SIZE 1024

#pragma INITCODE

VOID RtlTest()

{

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

    //用零填充内存

    RtlZeroMemory(pBuffer, BUFFER_SIZE);

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

    //用固定字节填充内存

    RtlFillMemory(pBuffer2, BUFFER_SIZE, 0xAA);

    //内存复制

    RtlCopyMemory(pBuffer, pBuffer2, BUFFER_SIZE);

    //判断内存是否一致

    ULONG ulRet = RtlCompareMemory(pBuffer, pBuffer2, BUFFER_SIZE);

    if(ulRet == BUFFER_SIZE)

    {

        KdPrint(("The two blocks are same. \n"));

    }

}

 

使用C++特性分配内存

//全局new操作符

void* _cdecl operator new(size_t size,POOL_TYPE PoolType=PagedPool)

{

    KdPrint(("Global operator new \n"));

    KdPrint(("Allocate size :%d\n", size));

    return ExAllocatePool(PoolType, size);

}



//全局delete操作符

void _cdecl operator delete(void* pointer)

{

    KdPrint(("Global delete operator\n"));

    return ExFreePool(pointer);

}



class TestClass

{

public:

    //构造函数

    TestClass()

    {

        KdPrint(("TestClass::TestClass()\n"));

    }



    //析构函数

    ~TestClass()

    {

        KdPrint(("TestClass::~TestClass()\n"));

    }



    //类中的new操作符

    void* operator new(size_t size,POOL_TYPE PoolType=PagedPool)

    {

        KdPrint(("TestClass::new\n"));

        KdPrint(("Allocate size :%d\n", size));

        return ExAllocatePool(PoolType, size);

    }

    //类中的delete操作符

    void operator delete(void* pointer)

    {

        KdPrint(("TestClass::delete\n"));

        return ExFreePool(pointer);

    }

private:

    char buffer[1024];

};



void TestNewOperator()

{

    //测试new操作

    TestClass* pTestClass = new TestClass;

    //测试delete操作符

    delete pTestClass;



    pTestClass = new(NonPagedPool) TestClass;

    delete pTestClass;



    char* pBuffer = new(PagedPool) char[100];

    delete []pBuffer;



    pBuffer = new(NonPagedPool) char[100];

    delete []pBuffer;

}

 

 

你可能感兴趣的:(windows)