转载: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. eclipse 把鼠标指针放在错误的语句上 提示快速修正 不见了的解决方法

    Window->Preferences->Java->Editor->Hovers 将[Combined Hover]选择即可,如果第一个[Variable Values]已经 ...

  2. 4.后台管理系统中的ajax提交或保存的两次模态框确认

    $(function () {         $('.ajaxForm').ajaxForm({         beforeSubmit:showPleaseWait,//提交之前        ...

  3. vue中上传图片至阿里云oss

    1.开通阿里云的oss服务这些这里就不多做介绍了 2.登入阿里云的后台管理系统创建一个Bucket 3.在后台管理系统中进入访问控制 4.点击用户管理->新建用户->填写相关信息,就生成了 ...

  4. LA 4992 Jungle Outpost(半平面交)

    Jungle Outpost [题目链接]Jungle Outpost [题目类型]半平面交 &题解: 蓝书282 我自己写的代码居然AC了!!! 刘汝佳的说要right要-3什么的,还要特判 ...

  5. Bootstrap-全局CSS样式-图片样式

    Bootstrap第二部分:全局CSS样式-图片样式.img-rounded   圆角图片.img-circle    圆形图片.img-thumbnail 缩略图片.img-responsive响应 ...

  6. vs2017创建支持多框架(net4.6.1;net4.6.2;netstandard2.0;netcoreapp2.0)版本

    1.新建netcore或netstandard或net4.6.1项目 2.编辑项目文件: <Project Sdk="Microsoft.NET.Sdk">   < ...

  7. SQL中的replace函数

    REPLACE 用第三个表达式替换第一个字符串表达式中出现的所有第二个给定字符串表达式. 语法 REPLACE ( 'string_expression1' , 'string_expression2 ...

  8. RDD、DataFrame、Dataset三者三者之间转换

    转化: RDD.DataFrame.Dataset三者有许多共性,有各自适用的场景常常需要在三者之间转换 DataFrame/Dataset转RDD: 这个转换很简单 val rdd1=testDF. ...

  9. Rpgmakermv(25) 游戏数据

    随着对RMMV插件了解的深入,我们会发现如果我们想要对游戏数据进行一些扩展,首先要了解游戏数据,游戏数据在官方代码中的rpg_managers.js里,这一节我们将要对这个官方类有一些基础的了解,并且 ...

  10. ASP.Net 中操作Ajax

    有时候,越深入去了解一个点,越发觉得自己无知,而之前当自己晓得一两个片面的点还洋洋自得,殊不知,这是多么讽刺,JQuery中有很多优势,比如异步提交值,部分刷新,给用户很好的体验感.目前为止,大部分项 ...