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

     

    2VOID 
      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"));

    }

  • 相关阅读:
    解决ASP.NET MVC AllowAnonymous属性无效导致无法匿名访问控制器的问题
    ASP.NET MVC 4 RC的JS/CSS打包压缩功能 (转载)
    oracle报错ORA-01507
    oracle 大表删除数据后,回收空间的问题。
    解决MySQL服务启动时报1067错误
    尚未在 Web 服务器上注册 ASP.NET 4.0” 的解决办法
    thymeleaf中相对路径的两种方式
    史上最详 Thymeleaf 使用教程
    isNotBlank()和isNotEmpty()总结
    IDEA去除掉虚线,波浪线,和下划线实线的方法
  • 原文地址:https://www.cnblogs.com/forlina/p/2116191.html
Copyright © 2020-2023  润新知