转载: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. C# 图片 旋转和翻转 RotateFlip

    1.Rotate90FlipX2.Rotate90FliY3.Rotate90FlipXY4.Rotate90FlipNone以上面四个为例:1是指定后接水平翻转的90度顺时针旋转,2是指定后接垂直翻 ...

  2. Mysql导出(多张表)表结构及表数据 mysqldump用法

        命令行下具体用法如下:  mysqldump -u用戶名 -p密码 -d 數據库名 表名 脚本名; 1.导出數據库為dbname的表结构(其中用戶名為root,密码為dbpasswd,生成的脚 ...

  3. C语言---选择结构和循环结构

    C语言的两种选择语句,1) if语句; 2) switch语句; 在if判断语句中,一般使用关系表达式. 关系运算符: <.<=.>.>=.==.!= 关系表达式:用关系运算符 ...

  4. Java IO留存查看

    IO也可以写作为 "i/O" ,也可以理解为In和Out,即输入与输出.所以,IO体系的基本功能就是: 读和写. IO流作用:读写设备上的东西,硬盘文件.内存.键盘.网络... 根 ...

  5. spring aop:aspectj-autoproxy 配置

    经常遇到aop-aspectJ的通知不被执行的问题 解决方法:http://blog.csdn.net/qwdafedv/article/details/53005210 首先,确保配置文件都已经是正 ...

  6. yum 与 apt 的对比

    一.概念 使用yum/apt之前,你很可能会遇到配置源(ubuntu下一般内置的就比较好,所以可能很少人手动配置),那这个源是什么呢,就是告诉apt/yum,安装软件的时候你要从哪里下载.比如你使用1 ...

  7. Sqoop 学习之路

    sqoop 基础知识和基本操作可以参考这篇博客:https://www.cnblogs.com/qingyunzong/p/8807252.html#_label3

  8. python locust 性能测试:locust安装和一些参数介绍

    安装参考 https://www.cnblogs.com/fnng/p/6081798.html <虫师大大的,很详细> ps:python3.7暂不支持locust:python3安装建 ...

  9. Spring boot 问题总结

    1. Spring boot 嵌入的tomcat不能启动: Unregistering JMX-exposed beans on shutdown   在官网(http://start.spring. ...

  10. Linux基础命令---添加用户useradd

    useradd 创建新的系统用户,useradd指令只能以管理员的身份运行,创建的用户都在“/etc/passwd”文件中.当不加-D参数,useradd指令使用命令列来指定新帐号的设定值and使用系 ...