• 对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; }

    源代码下载:https://files.cnblogs.com/nbsofer/list_entry.7z
    女孩不哭(QQ:191035066)@2013-02-25 13:45:50 http://www.cnblogs.com/nbsofer

  • 相关阅读:
    OpenJudge 2753 菲波那契数列
    Jmeter的介绍、安装及汉化
    spring集成Java性能监控调优工具-Javamelody
    js-xlsx + handsontable + echarts实现excel上传编辑然后显示成图表
    spring mybatis设置SQL语句打印
    Ribbon负载均衡策略详解
    JVM内存结构、Java内存模型以及Java对象模型之间的区别
    Java的自动拆装箱
    elasticsearch集群管理指南
    ElasticSearch最全分词器比较及使用方法
  • 原文地址:https://www.cnblogs.com/memset/p/2931980.html
Copyright © 2020-2023  润新知