• 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;
    }
  • 相关阅读:
    用R语言中的神经网络预测时间序列:多层感知器和极限学习机
    R语言SIR模型(Susceptible Infected Recovered Model)代码sir模型实例
    confirmit中 domainValues() 方法
    confirmit中indexOf()方法
    confitmit中none()方法
    confirmit中any()方法参数问题
    confirmit中方法调用的数组之sort()区别
    confirmit平台问题汇总
    confirmit中创建的 if 判断条件的区别
    专业名称解释笔记
  • 原文地址:https://www.cnblogs.com/qintangtao/p/3011986.html
Copyright © 2020-2023  润新知