zoukankan      html  css  js  c++  java
  • windows内核驱动内存管理之Lookaside使用

    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 INITCODE
    VOID LookasideTest()
    {
    	// 初始化
    	PAGED_LOOKASIDE_LIST pageList;
    	ExInitializePagedLookasideList(&pageList, NULL, NULL, 0, sizeof(MYDATASTRUCT), '1234', 0);
    
    	#define ARRAY_NUMBER 50
    
    	PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER];
    
    	// 模拟频繁申请内存
    	for(int i = 0; i< ARRAY_NUMBER; i++)
    	{
    		MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList);
    		KdPrint(("正在申请第%d个内存
    ", i+1));
    	}
    
    	// 模拟频繁回收内存
    	for(int i = 0; i<ARRAY_NUMBER;i++)
    	{
    		ExFreeToPagedLookasideList(&pageList, MyObjectArray[i]);
    
    		MyObjectArray[i] = NULL;
    
    		KdPrint(("正在回收第%d个空间
    ", i+1));
    
    	}
    
    	// 删除LokkList
    	ExDeletePagedLookasideList(&pageList);
    
    }
    
    
    
    /************************************************************************
    * 函数名称:DriverEntry
    * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
    * 参数列表:
          pDriverObject:从I/O管理器中传进来的驱动对象
          pRegistryPath:驱动程序在注册表的中的路径
    * 返回 值:返回初始化驱动状态
    *************************************************************************/
    #pragma INITCODE
    extern "C" NTSTATUS DriverEntry (
    			IN PDRIVER_OBJECT pDriverObject,
    			IN PUNICODE_STRING pRegistryPath	) 
    {
    	NTSTATUS status;
    	KdPrint(("Enter DriverEntry
    "));
    
    	//注册其他驱动调用函数入口
    	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
    "));
    	return status;
    }
    
    /************************************************************************
    * 函数名称:CreateDevice
    * 功能描述:初始化设备对象
    * 参数列表:
          pDriverObject:从I/O管理器中传进来的驱动对象
    * 返回 值:返回初始化状态
    *************************************************************************/
    #pragma INITCODE
    NTSTATUS CreateDevice (
    		IN PDRIVER_OBJECT	pDriverObject) 
    {
    	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 PAGEDCODE
    VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) 
    {
    	PDEVICE_OBJECT	pNextObj;
    	KdPrint(("Enter DriverUnload
    "));
    	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 PAGEDCODE
    NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
    								 IN PIRP pIrp) 
    {
    	KdPrint(("Enter HelloDDKDispatchRoutine
    "));
    	NTSTATUS status = STATUS_SUCCESS;
    	// 完成IRP
    	pIrp->IoStatus.Status = status;
    	pIrp->IoStatus.Information = 0;	// bytes xfered
    	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    	KdPrint(("Leave HelloDDKDispatchRoutine
    "));
    	return status;
    }
    


    /************************************************************************
    * 文件名称:driver.h                                                 
    * 作    者:Geons
    * 完成日期:2016年3月26日17:44:19
    *************************************************************************/
    #pragma once
    
    #ifdef __cplusplus
    extern "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是不会出现这个报错问题的


  • 相关阅读:
    常见的灰度发布系统规则
    golang中的路由分组
    艾森豪威尔矩阵
    列文定理
    吃狗粮定理
    mysql事务 锁
    mysql中explain优化分析
    mysql hash索引优化
    各种浏览器内核介绍
    浏览器 兼容性问题总结
  • 原文地址:https://www.cnblogs.com/geons/p/8685176.html
Copyright © 2011-2022 走看看