windows驱动开发技术详解 第五章 windows内存管理

来源:互联网 发布:yy网络用语什么意思 编辑:程序博客网 时间:2024/05/21 17:07

1.      内存管理概念

1.1   物理内存概念

1.2   虚拟内存

DDK中宏PAGE_SIZE记录分页大小,一般为4KB。

1.3   用户模式地址和内核模式地址

低2G的虚拟地址为用户模式地址,为0~0X7FFFFFFF。

高2G的虚拟地址为内核模式地址,为0X80000000~0XFFFFFFFF。

进程切换时,内核地址完全相同,只改变用户模式地址的映射。

1.4  windows驱动程序和进程的关系

windows驱动程序的不同例程运行在不同的进程中。DriverEntry和AddDevice例程运行在系统(System)进程中。其他一些例程运行在应用程序的上下文。

技巧:用PsGetCurrentProcess()函数可以得到当前进程,打印出来可以显示出当前进程的进程名,用DebugView软件查看log信息。

VOID DisplayItsProcessName()

{

       //得到当前进程

       PEPROCESSpEProcess = PsGetCurrentProcess();

       //等到当前进程名称,0x174偏移位置对应ImageFileName

       PTSTRProcessName = (PTR)((ULONG)pEProcess + 0x174;

       KdPrint((“%s\n”,ProcessName));

}

1.5 分页与非分页内存

分页内存:虚拟内存页面可以交换到文件中

非分页内存:虚拟内存页面永远不会交换到文件中。

注意:当程序的中断请求级在DISPATCH_LEVEL之上时(包括DISPATCH_LEVEL),程序只能使用非分页内存,否则将导致蓝屏死机。

 

在编译DDK提供的例程时,指定某个例程和某个局部变量载入分页内存还是非分页内存,需做如下定义。常放在头文件中。

#define PAGEDCODEcode_seg("PAGE")

#define LOCKEDCODE code_seg()

#define INITCODEcode_seg("INIT")

 

#define PAGEDDATAdata_seg("PAGE")

#define LOCKEDDATA data_seg()

#define INITDATAdata_seg("INIT")

将某个函数载入到分页内存中:

#pragma PAGEDCODE

VOID SomeFunction ()

{

    PAGED_CODE();

    //Do something

}

PAGED_CODE()是DDK提供的宏,只在check版本中生效。会检验函数是否运行低于DISPATCH_LEVEL的中断请求级别,若高于或等于这个级别将产生一个断言。

将函数载入非分页内存中:

#pragma LOCKEDCODE

VOID SomeFunction ()

{

    //Do something

}

例程初始化的时候载入内存,然后就可以从内存卸载掉:

#pragma INITCODE

extern "C" NTSTATUSDriverEntry (

                  IN PDRIVER_OBJECT pDriverObject,

                  IN PUNICODE_STRING pRegistryPath   )

{

//Do something

}

1.6 分配内核内存

局部变量是放在栈(Stack)空间中的,但栈空间较小,所以驱动程序不适合递归调用或者局部变量是大的结构体。若需要大的结构体,请在堆(Heap)中申请。

堆中申请内存的函数:

PVOID //返回分配的内存地址,返回0表示分配内存失败

  ExAllocatePool(

         IN POOL_TYPE  PoolType, //NonPagedPool或PagedPool

         IN SIZE_T NumberOfBytes  //最好是4的倍数

  );

PVOID

  ExAllocatePoolWithTag( //多分配4个字节的标签

         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

);

PoolType可以指定以下几种:

  NonPagedPool

  PagedPool

NonPagedPoolMustSucceed

NonPagedPoolCacheAligned:分配非分页内存,且必须内存对齐

PagedPoolCacheAligned

NonPagedPoolCacheAlignedMustS:必须成功

回收内存:ExFreePool和ExFreePoolWithTag

       VOID

              ExFreePool(

                     INPVOID P //要释放的地址

              );

NTKERNELAPI

       VOID

              ExFreePoolWithTag(

                     INPVOID P,

IN ULONG Tag

              );

 


0 0
原创粉丝点击