(四)、在驱动中使用链表和快查表
一、链表
1、代码
#include <ntddk.h> typedef struct _MyLink { LIST_ENTRY ListEntry; int number; } MyLink,*pMyLink; void LinkTest() { LIST_ENTRY List_Head; InitializeListHead(&List_Head);//初始化链表// int i = 1; for ( i = 1; i <= 10; i++) { pMyLink pLink = (pMyLink)ExAllocatePool(PagedPool, sizeof(MyLink)); pLink->number = i; InsertHeadList(&List_Head, &pLink->ListEntry); //头插// } while (!IsListEmpty(&List_Head)) { PLIST_ENTRY pGet = RemoveHeadList(&List_Head); pMyLink pdata = CONTAINING_RECORD(pGet, MyLink, ListEntry);//宏//可以返回基地址// DbgPrint("%d\n", pdata->number); ExFreePool(pdata); } } VOID Unload(PDRIVER_OBJECT driver) { DbgPrint("驱动xie载\n"); } NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) { DbgPrint("加载\n"); LinkTest(); driver->DriverUnload = Unload; return STATUS_SUCCESS; }
2、实验
二、快查表
1、基本概念
快查表又称后备链表,只有内核可以使用
windows内核空间十分庞大,如果我们频繁申请内存,操作系统就会在可用内存中反复寻找找到可用内存页,这样会降低系统效率,使内存出现大量空洞。
快查表是一组是事先分配的相同尺寸的内存块,这些块有些在使用,有些没被使用。当有内存分配请求的时候,系统会遍历这个列表寻找最近的未分配的块。
如果未分配的块找到了,分配请求就很快被满足了。否则系统必须从分页或不分页内存池去分配。
2、所用函数
左边带N的函数是分配非分页内存的函数,右边是分配分页内存的函数
3、代码
//打错了,应该是LookAsideList// #include<ntddk.h> typedef struct _MYDATA { int num; }MYDATA,*pMYDATA; VOID UnLoad(PDRIVER_OBJECT driver) { DbgPrint("driver unLoad\n"); } VOID testLookSide() { PAGED_LOOKASIDE_LIST LookAsideList; ExInitializePagedLookasideList(&LookAsideList,NULL,NULL,0,sizeof(MYDATA),'ASDF',0); //初始化分页的快查表//分配一些符合条件的内存块//微软要求单引号,但双引号貌似也可以// pMYDATA pdata[100] = { NULL }; for (int i = 0; i < 100; i++) { pdata[i] = ExAllocateFromPagedLookasideList(&LookAsideList);//从快查链表中分配出来// pdata[i]->num = i; } DbgPrint("分页快查表测试\n"); for (int i = 0; i < 100; i++) { //DbgPrint("..........\n"); DbgPrint("%p\n", pdata[i]); ExFreeToPagedLookasideList(&LookAsideList, pdata[i]);// } ExDeletePagedLookasideList(&LookAsideList);//删除后备链表// } NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path) { DbgPrint("driver Load\n"); driver->DriverUnload = UnLoad; testLookSide(); return STATUS_SUCCESS; }