转载: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=; it<; 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=; it<; 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"));
}
}
}

[内核驱动] 链表LIST_ENTRY的操作(转)的更多相关文章

  1. Windows内核驱动中操作文件

    本页主题:如何在windows内核驱动中对文件操作,实现对文件的拷贝.粘贴.删除.查询信息等,这是很常用也是很简单的方法. 部分内容参考:http://www.cppblog.com/aurain/a ...

  2. linux内核之链表操作解析

    本文只是对linux内核中的链表进行分析.内核版本是linux-2.6.32.63.文件在:linux内核/linux-2.6.32.63/include/linux/list.h.本文对list.h ...

  3. linux 内核的链表操作(好文不得不转)

    以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...

  4. Linux内核驱动学习(七)应用层直接操作GPIO

    文章目录 简介 原理图 节点 设置为输出 设置为输入 映射关系 debugfs pwm demo 简介 前面通过libgpio的方式介绍了内核空间对GPIO进行操作的接口,其做了较好的封装,同时Lin ...

  5. Linux内核【链表】整理笔记(2)

    关于链表我们更多时候是对其进行遍历的需求,上一篇博文里我们主要认识了一下和链表操作比较常用的几个内核API接口,其入参全都是清一色的struct list_head{}类型.至于链表的遍历,内核也有一 ...

  6. linux内核驱动模型

    linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构 ...

  7. Linux内核中链表实现

    关于双链表实现,一般教科书上定义一个双向链表节点的方法如下: struct list_node{ stuct list_node *pre; stuct list_node *next; ElemTy ...

  8. linux内核中链表代码分析---list.h头文件分析(二)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...

  9. (笔记)Linux内核中内存相关的操作函数

    linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...

随机推荐

  1. react native初识

    开发的第一步就是搭建rn的开发环境,你可以去官网去查看教程也可以 点击 http://bbs.reactnative.cn/topic/10 进去查看window的开发环境安装的教程:注意:很关键的一 ...

  2. SQLAllocHandle

    函数定义: 顾名思义,该函数就是用来分配句柄的,句柄类型参考参数详解. SQLRETURN SQLAllocHandle( SQLSMALLINT     HandleType, SQLHANDLE  ...

  3. 20165305 苏振龙《Java程序设计》第八周课上测试补做

    1. 下载附件中的world.sql.zip, 参考http://www.cnblogs.com/rocedu/p/6371315.html#SECDB,导入world.sql,提交导入成功截图 2. ...

  4. interface接口——公共规范标准

    黑马课程学习记录: 个人理解也可以看成一个类:源代码还是.java,编译后的字节文件还是.class 抽象类中可以含有普通成员方法,但是有抽象方法的必须是抽象类或者接口, 接口中只能含有抽象方法: 创 ...

  5. Linux基础命令---文本格式转换expand,unexpand

    expand 将文件中的tab转换成空格,结果送到标准输出.如果没有指定文件,那么从标准输入读取. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.F ...

  6. 证券化代币的时代已经到来,STO将引爆区块链经济

    STOs 似乎会在 2019 年取代 ICOs,即使不是完全取代,但置换的比例也会相当大.所有在美上市的公司都将按照 SEC 制定的相关规定进行交易.Vellum Capital 的 CEO 兼管理合 ...

  7. docker能用来干嘛

    http://blog.csdn.net/wangtaoking1/article/details/44340445   什么是Docker Docker 是一个开源项目,诞生于 2013 年初,最初 ...

  8. 安装PG3.0详细教程附图

    从公司要求开始着手调研PG到今天上午都还不知道如何安装PG.. 囧的离谱.. 看了半天的PG官网 就这个网页我瞅了半天..对你没看错 半天 少说有10分钟..原谅我的英文不是非常好..但是我知道什么意 ...

  9. P1258 小车问题

    P1258 小车问题 蒟蒻精神自强不息蒟蒻精神永不言败加油加油ヾ(◍°∇°◍)ノ゙yeah yeah yeah 据说这是道小学奥数题抱歉蒟蒻的我没学过奥数,算了大概三大张演草纸,不得不说这题对于蒟蒻本 ...

  10. Django框架----命名空间模式

    命名空间模式 即使不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL. 举个例子: project中的urls.py from django.conf.urls im ...