《Windows内核安全与驱动开发》阅读笔记 -- 索引目录
《Windows内核安全与驱动开发》 3.2 内存与链表
1. 尝试生成一个链表头并将其初始化。
2. 尝试向内存中申请两个链表结点,并且初始化该结点,将该结点插入到链表中,其数据结构如下。
typedef struct { LIST_ENTRY list_entry; INT id; }StuInfo,*PStuInfo;
3. 遍历“问题2”中生成的链表,并调用 DbgPrint 打印出来。
4. 将问题2中的链表清空(并释放内存),最后判断该链表是否为空。
5. 有几种删除链表结点的方法。
6. 遍历链表时,如果 LIST_ENTRY 成员不在开头,应该如何操作?
答案
1. 尝试生成一个链表头并将其初始化。
// 定义并初始化链表头 LIST_ENTRY my_list_entry; InitializeListHead(&my_list_entry);
2. 尝试向内存中申请两个链表结点,并且初始化该结点,将该结点插入到链表中,其数据结构如下。
// // 向内存中申请一个结点,并插入到链表中。 // PStuInfo pStu1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo),MEN_NAME); if (!pStu1) { return STATUS_INSUFFICIENT_RESOURCES; } pStu1->id = 123; InsertHeadList(&my_list_entry, (PLIST_ENTRY) pStu1); PStuInfo pStu2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo), MEN_NAME); if (!pStu2) { return STATUS_INSUFFICIENT_RESOURCES; } pStu2->id = 456; InsertHeadList(&my_list_entry, (PLIST_ENTRY)pStu2);
3. 遍历“问题2”中生成的链表,并调用 DbgPrint 打印出来
// // 遍历链表 // for (PLIST_ENTRY p = my_list_entry.Flink; p != &my_list_entry; p = p->Flink) { DbgPrint("%d\n", ((PStuInfo)p)->id); }
4. 将问题2中的链表清空(并释放内存),最后判断该链表是否为空。
// // 全部删除链表 // PLIST_ENTRY p; while (!IsListEmpty(&my_list_entry)) { p = RemoveHeadList(&my_list_entry); // 获取被移除链表元素 ExFreePool((PStuInfo)p); } // 判断链表是否为空 if (IsListEmpty(&my_list_entry)) { DbgPrint("链表已空\n"); } else { DbgPrint("链表未空\n"); }
5. 三种方法,移除链表头(RemoveHeadList);移除链表尾(RemoveTailList);移除中间元素(RemoveEntryList)。
6. 使用一个宏 CONTAINING_RECORD.
完整代码:
1 #include2 #define MEN_NAME 'abc' 3 // 定义链表结构 4 typedef struct { 5 LIST_ENTRY list_entry; 6 INT id; 7 }StuInfo,*PStuInfo; 8 9 10 11 //提供一个卸载函数,让程序能卸载,如果没有这个函数,驱动将不能卸载。 12 VOID UnDriver(PDRIVER_OBJECT driver) 13 { 14 KdPrint(("卸载驱动成功")); 15 } 16 //入口函数,相当于main。 17 NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) 18 { 19 // 定义并初始化链表头 20 LIST_ENTRY my_list_entry; 21 InitializeListHead(&my_list_entry); 22 23 // 24 // 向内存中申请一个结点,并插入到链表中。 25 // 26 PStuInfo pStu1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo),MEN_NAME); 27 if (!pStu1) { 28 return STATUS_INSUFFICIENT_RESOURCES; 29 } 30 pStu1->id = 123; 31 InsertHeadList(&my_list_entry, (PLIST_ENTRY) pStu1); 32 33 PStuInfo pStu2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo), MEN_NAME); 34 if (!pStu2) { 35 return STATUS_INSUFFICIENT_RESOURCES; 36 } 37 pStu2->id = 456; 38 InsertHeadList(&my_list_entry, (PLIST_ENTRY)pStu2); 39 40 // 41 // 遍历链表 42 // 43 for (PLIST_ENTRY p = my_list_entry.Flink; p != &my_list_entry; p = p->Flink) { 44 DbgPrint("%d\n", ((PStuInfo)p)->id); 45 } 46 47 // 48 // 全部删除链表 49 // 50 PLIST_ENTRY p; 51 52 while (!IsListEmpty(&my_list_entry)) { 53 p = RemoveHeadList(&my_list_entry); // 获取被移除链表元素 54 ExFreePool((PStuInfo)p); 55 56 } 57 58 // 判断链表是否为空 59 if (IsListEmpty(&my_list_entry)) { 60 DbgPrint("链表已空\n"); 61 } 62 else { 63 DbgPrint("链表未空\n"); 64 } 65 66 driver->DriverUnload = UnDriver; 67 return STATUS_SUCCESS; 68 }