[內核驅動] 鏈表LIST_ENTRY的操作(轉)


轉載: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")); } }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM