转载:https://www.cnblogs.com/forlina/archive/2011/08/11/2134610.html
转载:http://www.xuebuyuan.com/1544347.html
转载:http://blog.chinaunix.net/uid-24789420-id-3045264.html
转载:https://www.cnblogs.com/nbsofer/archive/2013/02/25/2931980.html(☆)
遍历:
//list_entry.c #include <ntddk.h> //我的自定义数据类型,包含LIST_ENTRY结构体 typedef struct{ int num; LIST_ENTRY list; }MY_DATA,*PMY_DATA; void TestListEntry(void) { //定义一个头结点,不需要包含数据域,直接LIST_ENTRY就行了 LIST_ENTRY list_head; PLIST_ENTRY p = NULL; int it; //初始化头结点,必须 InitializeListHead(&list_head); //第1步:初始化测试数据 for(it=0; it<16; it++){ //循环调用ExAllocatePool分配内存 PMY_DATA pmd = (PMY_DATA)ExAllocatePool(PagedPool,sizeof(MY_DATA)); //数据域,我只定义了一个int类型变量,赋值 pmd->num = it; //头插法,注意是&pmd->list //也可以换成InsertTailList从尾部插入结点 //InsertTailList(&list_head,&pmd->list); InsertHeadList(&list_head,&pmd->list); } //第2步:遍历双向链表(结点不被移除), //p=list_head.Flink指向第1个结点 //若链表为空:list_head.Flink/Blink == &list_head KdPrint(("顺序遍历双向链表:\n")); //注意是p!=&list_head,其实,<<楚狂人Windows驱动编程基础教程.pdf>>中 //就把这个弄错了, 它是p!=&list_head.flink for(p=list_head.Flink; p!=&list_head; p=p->Flink){ //用CONTAINING_RECORD得到MY_DATA的指针 //有关CONTAINING_RECORD的详细解说见我的另一篇文章 //http://~ PMY_DATA pmd = CONTAINING_RECORD(p,MY_DATA,list); KdPrint(("pmd->num:%d\n",pmd->num)); } KdPrint(("反序遍历双向链表:\n")); for(p=list_head.Blink; p!=&list_head; p=p->Blink){ PMY_DATA pmd = CONTAINING_RECORD(p,MY_DATA,list); KdPrint(("pmd->num:%d\n",pmd->num)); } //第3步:dump所有的结点指针(结点被移除) KdPrint(("Dump所有结点:\n")); while(!IsListEmpty(&list_head)){ //得到MY_DATA指针中LIST_ENTRY成员list的指针 //注意该结点已经被移除,list_head双向链表中已经不存在该结点 //也可以换成RemoveTailList从尾部移除结点 //PLIST_ENTRY plist = RemoveTailList(&list_head); PLIST_ENTRY plist = RemoveHeadList(&list_head); PMY_DATA pmd = CONTAINING_RECORD(plist,MY_DATA,list); //打印出保存的数据,并验证程序结果 KdPrint(("pmd->num=%d\n",pmd->num)); //结点已经被移除,使用完就可释放了 //注意释放的是整体的pmd指针,而不是plist ExFreePool(pmd); } } void DriverUnload(PDRIVER_OBJECT pDriverObject) { } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath) { pDriverObject->DriverUnload = DriverUnload; TestListEntry(); return STATUS_SUCCESS; }
源代码下载:http://files.cnblogs.com/nbsofer/list_entry.7z
链接:https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-removeentrylist
遍历链表找出指定字符串Remove:
移除的时候用到函数:
RemoveEntryList
typedef struct{ int num; LIST_ENTRY list; }MY_DATA,*PMY_DATA; void TestListEntry(int num) { //定义一个头结点,不需要包含数据域,直接LIST_ENTRY就行了 LIST_ENTRY list_head; PLIST_ENTRY p = NULL; int it; //初始化头结点,必须 InitializeListHead(&list_head); //第1步:初始化测试数据 for(it=0; it<16; it++){ //循环调用ExAllocatePool分配内存 PMY_DATA pmd = (PMY_DATA)ExAllocatePool(PagedPool,sizeof(MY_DATA)); //数据域,我只定义了一个int类型变量,赋值 pmd->num = it; //头插法,注意是&pmd->list //也可以换成InsertTailList从尾部插入结点 //InsertTailList(&list_head,&pmd->list); InsertHeadList(&list_head,&pmd->list); } //注意是p!=&list_head,其实,<<楚狂人Windows驱动编程基础教程.pdf>>中 //就把这个弄错了, 它是p!=&list_head.flink for(p=list_head.Flink; p!=&list_head; p=p->Flink)
{ //用CONTAINING_RECORD得到MY_DATA的指针 //有关CONTAINING_RECORD的详细解说见我的另一篇文章 PMY_DATA pmd = CONTAINING_RECORD(p,MY_DATA,list); if(pmd->num==num) { KdPrint(("num1 and num2 are equal\n")); RemoveEntryList(&pmd->list); } else { KdPrint(("num1 and num2 are NOT equal\n")); } }
}