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;
}
原文地址:https://www.cnblogs.com/qintangtao/p/3011986.html