對WDK中LIST_ENTRY的遍歷


  這篇文章是講WDK中的LIST_ENTRY的遍歷的, 前一篇文章(對WDK中對LIST_ENTRY的操作的相關函數的實現及簡單運用)是
講的實現方式. 都已經實現了,遍歷當然已經不是問題了.  

//list_entry.c
#include <ntddk.h>

/**********************************************************
文件名稱:list_entry.c
文件路徑:./list_entry/list_entry.c
創建時間:2013-2-4,22:49:43
文件作者:女孩不哭
文件說明:該文件實現對WDK中LIST_ENTRY雙向鏈表的操作:
遍歷,插入,移除~
    若想了解對LIST_ENTRY的操作系統函數的實現,見:
http://www.cnblogs.com/nbsofer/archive/2013/02/25/2931965.html
**********************************************************/

//我的自定義數據類型,包含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
女孩不哭(QQ:191035066)@2013-02-25 13:45:50 http://www.cnblogs.com/nbsofer


免責聲明!

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



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