[Windows驱动开发]内存申请与释放的三种方式

#include 
#ifdef __cplusplus
//此处是全局new,delete,new[],delete[]的重载,这是必要的
void* operator new(size_t size, POOL_TYPE PoolType = PagedPool) {
    KdPrint(("new%I64u\n", size));
    return ExAllocatePool(PoolType, size);
}
void* operator new[](size_t size, POOL_TYPE PoolType = PagedPool) {
    KdPrint(("new[]%I64u\n", size));
    return ExAllocatePool(PoolType, size);
}
void operator delete(void *pointer) {
    KdPrint(("delete\n"));
    ExFreePool(pointer);
}
void operator delete[](void* pointer) {
    KdPrint(("delete[]\n"));
    ExFreePool(pointer);
}
#endif

typedef struct _MYDATASTRUCT {
    CHAR buffer[64];
}MYDATASTRUCT, *PMYDATASTRUCT;
//malloc与free的例子
NTSTATUS Fun1(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {

    //Tag是由单引号分隔的 1 到 4 个字符的非零字符文本, (例如,'Tag1')
    //标记中的每个 ASCII 字符必须是要0x7E (波形符) 0x20 (空格) 范围内的值

    /*--------------------寻常内存申请方式--------------------*/
    {
#define BUFFER_SIZE (100)   //申请的内存大小
        //获得局部内存
        PUCHAR pBuffer_ch[100] = { 0 };
        //过时api ExAllocatePool
        PUCHAR pBuffer1 = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);
        if (!pBuffer1) {
            //表示资源不足
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        //用零填充内存
        RtlZeroMemory(pBuffer1, BUFFER_SIZE);
        PUCHAR pBuffer2 = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);
        if (!pBuffer2) {
            ExFreePool(pBuffer1);
            //表示资源不足
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        //用固定字节填充内存
        RtlFillMemory(pBuffer2, BUFFER_SIZE, 0xAA);
        //内存拷贝
        RtlCopyMemory(pBuffer1, pBuffer2, BUFFER_SIZE);
        RtlCopyMemory(pBuffer2, pBuffer_ch, BUFFER_SIZE);
        //判断内存是否一致:没错,相等的时候就返回BUFFER_SIZE
        ULONG ulRet = RtlCompareMemory(pBuffer1, pBuffer2, BUFFER_SIZE);
        if (BUFFER_SIZE == ulRet) {
            DbgPrint("SFilter!: same1\n");
        }
        ulRet = RtlCompareMemory(pBuffer_ch, pBuffer2, BUFFER_SIZE);
        if (BUFFER_SIZE == ulRet) {
            DbgPrint("SFilter!: same2\n");
        }
        ExFreePool(pBuffer1);
        ExFreePool(pBuffer2);

        //仍是过时的另一种内存申请与释放:第三个参数是指向标签的地址
        PUCHAR pBuffer3 = (PUCHAR)ExAllocatePoolWithTag(PagedPool, BUFFER_SIZE, 'Tag1');
        if (!pBuffer3) {
            //表示资源不足
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        ExFreePoolWithTag(pBuffer3, 'Tag1');

        //现用的内存申请与释放:第三个参数是指向标签的地址
        //不同于上面的,该函数申请的内存将自动置0
        PUCHAR pBuffer4 = (PUCHAR)ExAllocatePool2(POOL_FLAG_PAGED, BUFFER_SIZE, 'Tag1');
        if (!pBuffer4) {
            //表示资源不足
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        ExFreePoolWithTag(pBuffer4, 'Tag1');
#undef BUFFER_SIZE
    }

    /*--------------------通过快表内存申请方式--------------------*/
    {
        /*
        频繁的申请和回收内存,会导致在内存上产生大量的内存“空洞”,从而导致最终无法申请内存。
        DDK为程序员提供了Lookaside结构来解决这个问题。
        我们可以将Lookaside对象看成是一个内存容器。在初始化的时候,它先向Windows申请了一块比较大的内存。
        以后程序员每次申请内存的时候,不是直接向Windows申请内存,而是想Lookaside对象申请内存。
        Looaside会智能的避免产生内存“空洞”。
        如果Lookaside对象内部内存不够用时,它会向操作系统申请更多的内存。
        Lookaside一般会在以下情况下使用:
        1.       程序员每次申请固定大小的内存。
        2.       申请和回收的操作十分频繁。
        */
#define ARRAY_NUMBER 5
        //初始化Lookaside(快表)对象
        PAGED_LOOKASIDE_LIST pageList;
        //向系统申请内存,以设置快表的初始内存大小
        ExInitializePagedLookasideList(&pageList, NULL, NULL, 0, sizeof(MYDATASTRUCT), '1234', 0);
        //模拟频繁申请内存
        PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER];
        for (int i = 0; i < ARRAY_NUMBER; i++) {
            KdPrint(("ExAllocateFromPagedLookasideList\n"));
            MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList);
        }
        //模拟频繁回收内存for (int i=0;i
        for (int i = 0; i < ARRAY_NUMBER; i++) {
            KdPrint(("ExFreeToPagedLookasideList\n"));
            ExFreeToPagedLookasideList(&pageList, MyObjectArray[i]);
            MyObjectArray[i] = NULL;
        }
        //删除快表
        ExDeletePagedLookasideList(&pageList);
#undef ARRAY_NUMBER

    }

    /*--------------------通过C++的内存申请方式--------------------*/
    {
#ifdef __cplusplus
        int* a = new(PagedPool) int;
        operator delete(a);
        a = nullptr;

        a = new(PagedPool) int[100];
        operator delete[](a);
        a = nullptr;
        //如果是类就类内重载new,delete,new[],delete[]
        //此处忽略类
#endif
    }

    return STATUS_SUCCESS;
}
#ifdef __cplusplus
extern "C"
#endif
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT     DriverObject,   //驱动对象,由系统加载驱动时分配
    IN PUNICODE_STRING    RegistryPath    //记录驱动相关参数的注册表路径
)
{
    NTSTATUS status = STATUS_SUCCESS;
    DbgPrint("SFilter!:DriverEntry\n");
    status =Fun1(DriverObject, RegistryPath);

    return status;
}

你可能感兴趣的:(教程,驱动开发)