windows内核驱动内存管理之Lookaside使用

来源:互联网 发布:淘宝评论怎么没有了 编辑:程序博客网 时间:2024/05/16 02:00

Windows内存管理中使用了类似于容器的东西,叫做Lookaside对象,每次程序员申请内存都会从Lookaside里面申请,只有不足的时候,Lookaside才会向内存又一次申请内存空间,这样减少了频繁申请内存而导致的内存碎片。

当Lookaside对象内部有大量没有使用的内存时候,它会自动让windows回收一部分内存,总之,Lookaside很智能。

一般Lookaside用于以下情况:

(1)程序员每次申请固定的内存大小

(2)申请和回收内存的次数较多,很频繁

开发环境:

VS2012+WDK7.1


初始化Lookaside对象:

分页:

VOID ExInitializePagedLookasideList(  _Out_    PPAGED_LOOKASIDE_LIST Lookaside,  _In_opt_ PALLOCATE_FUNCTION    Allocate,  _In_opt_ PFREE_FUNCTION        Free,  _In_     ULONG                 Flags,  _In_     SIZE_T                Size,  _In_     ULONG                 Tag,  _In_     USHORT                Depth);

非分页:

VOID ExInitializeNPagedLookasideList(  _Out_    PPAGED_LOOKASIDE_LIST Lookaside,  _In_opt_ PALLOCATE_FUNCTION    Allocate,  _In_opt_ PFREE_FUNCTION        Free,  _In_     ULONG                 Flags,  _In_     SIZE_T                Size,  _In_     ULONG                 Tag,  _In_     USHORT                Depth);

回收内存

VOID ExFreeToPagedLookasideList(  _Inout_ PPAGED_LOOKASIDE_LIST Lookaside,  _In_    PVOID                 Entry);


全套测试代码:

/************************************************************************* 文件名称:main.cpp                                               * 作    者:Geons* 完成日期:2016年3月27日11:03:20*************************************************************************/#include "driver.h"typedef struct _MYDATASTRUCT{CHAR buffer[64];}MYDATASTRUCT, *PMYDATASTRUCT;#pragma INITCODEVOID LookasideTest(){// 初始化PAGED_LOOKASIDE_LIST pageList;ExInitializePagedLookasideList(&pageList, NULL, NULL, 0, sizeof(MYDATASTRUCT), '1234', 0);#define ARRAY_NUMBER 50PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER];// 模拟频繁申请内存for(int i = 0; i< ARRAY_NUMBER; i++){MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList);KdPrint(("正在申请第%d个内存\n", i+1));}// 模拟频繁回收内存for(int i = 0; i<ARRAY_NUMBER;i++){ExFreeToPagedLookasideList(&pageList, MyObjectArray[i]);MyObjectArray[i] = NULL;KdPrint(("正在回收第%d个空间\n", i+1));}// 删除LokkListExDeletePagedLookasideList(&pageList);}/************************************************************************* 函数名称:DriverEntry* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象* 参数列表:      pDriverObject:从I/O管理器中传进来的驱动对象      pRegistryPath:驱动程序在注册表的中的路径* 返回 值:返回初始化驱动状态*************************************************************************/#pragma INITCODEextern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath) {NTSTATUS status;KdPrint(("Enter DriverEntry\n"));//注册其他驱动调用函数入口pDriverObject->DriverUnload = HelloDDKUnload;pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;//创建驱动设备对象status = CreateDevice(pDriverObject); LookasideTest();KdPrint(("DriverEntry end\n"));return status;}/************************************************************************* 函数名称:CreateDevice* 功能描述:初始化设备对象* 参数列表:      pDriverObject:从I/O管理器中传进来的驱动对象* 返回 值:返回初始化状态*************************************************************************/#pragma INITCODENTSTATUS CreateDevice (IN PDRIVER_OBJECTpDriverObject) {NTSTATUS status;PDEVICE_OBJECT pDevObj;PDEVICE_EXTENSION pDevExt;//创建设备名称UNICODE_STRING devName;RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");//创建设备status = IoCreateDevice( pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)devName,FILE_DEVICE_UNKNOWN,0, TRUE,&pDevObj );if (!NT_SUCCESS(status))return status;pDevObj->Flags |= DO_BUFFERED_IO;pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;pDevExt->pDevice = pDevObj;pDevExt->ustrDeviceName = devName;//创建符号链接UNICODE_STRING symLinkName;RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");pDevExt->ustrSymLinkName = symLinkName;status = IoCreateSymbolicLink( &symLinkName,&devName );if (!NT_SUCCESS(status)) {IoDeleteDevice( pDevObj );return status;}return STATUS_SUCCESS;}/************************************************************************* 函数名称:HelloDDKUnload* 功能描述:负责驱动程序的卸载操作* 参数列表:      pDriverObject:驱动对象* 返回 值:返回状态*************************************************************************/#pragma PAGEDCODEVOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) {PDEVICE_OBJECTpNextObj;KdPrint(("Enter DriverUnload\n"));pNextObj = pDriverObject->DeviceObject;while (pNextObj != NULL) {PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;//删除符号链接UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;IoDeleteSymbolicLink(&pLinkName);pNextObj = pNextObj->NextDevice;IoDeleteDevice( pDevExt->pDevice );}}/************************************************************************* 函数名称:HelloDDKDispatchRoutine* 功能描述:对读IRP进行处理* 参数列表:      pDevObj:功能设备对象      pIrp:从IO请求包* 返回 值:返回状态*************************************************************************/#pragma PAGEDCODENTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) {KdPrint(("Enter HelloDDKDispatchRoutine\n"));NTSTATUS status = STATUS_SUCCESS;// 完成IRPpIrp->IoStatus.Status = status;pIrp->IoStatus.Information = 0;// bytes xferedIoCompleteRequest( pIrp, IO_NO_INCREMENT );KdPrint(("Leave HelloDDKDispatchRoutine\n"));return status;}


/************************************************************************* 文件名称:driver.h                                                 * 作    者:Geons* 完成日期:2016年3月26日17:44:19*************************************************************************/#pragma once#ifdef __cplusplusextern "C"{#endif#include <NTDDK.h>#ifdef __cplusplus}#endif #define PAGEDCODE code_seg("PAGE")#define LOCKEDCODE code_seg()#define INITCODE code_seg("INIT")#define PAGEDDATA data_seg("PAGE")#define LOCKEDDATA data_seg()#define INITDATA data_seg("INIT")#define arraysize(p) (sizeof(p)/sizeof((p)[0]))typedef struct _DEVICE_EXTENSION {PDEVICE_OBJECT pDevice;UNICODE_STRING ustrDeviceName;//设备名称UNICODE_STRING ustrSymLinkName;//符号链接名} DEVICE_EXTENSION, *PDEVICE_EXTENSION;// 函数声明NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp);VOID LookasideTest();

注意:

在用VS进行编译生成SYS时候,注意修改属性中的“链接器”->“常规”->“附加依赖项”,只需要填写“ntoskrnl.lib;wdm.lib;”,不能写多余的,否则驱动无法加载到系统中,会生成额外的不支持的DLL。

如果出现缓冲区异常,修改属性中的C/C++->代码生成->安全检查->否(/GS)

如果使用X86build是不会出现这个报错问题的


0 0
原创粉丝点击