[内核驱动] 链表LIST_ENTRY的操作(转)
转载: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的操作(转)的更多相关文章
- Windows内核驱动中操作文件
本页主题:如何在windows内核驱动中对文件操作,实现对文件的拷贝.粘贴.删除.查询信息等,这是很常用也是很简单的方法. 部分内容参考:http://www.cppblog.com/aurain/a ...
- linux内核之链表操作解析
本文只是对linux内核中的链表进行分析.内核版本是linux-2.6.32.63.文件在:linux内核/linux-2.6.32.63/include/linux/list.h.本文对list.h ...
- linux 内核的链表操作(好文不得不转)
以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...
- Linux内核驱动学习(七)应用层直接操作GPIO
文章目录 简介 原理图 节点 设置为输出 设置为输入 映射关系 debugfs pwm demo 简介 前面通过libgpio的方式介绍了内核空间对GPIO进行操作的接口,其做了较好的封装,同时Lin ...
- Linux内核【链表】整理笔记(2)
关于链表我们更多时候是对其进行遍历的需求,上一篇博文里我们主要认识了一下和链表操作比较常用的几个内核API接口,其入参全都是清一色的struct list_head{}类型.至于链表的遍历,内核也有一 ...
- linux内核驱动模型
linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构 ...
- Linux内核中链表实现
关于双链表实现,一般教科书上定义一个双向链表节点的方法如下: struct list_node{ stuct list_node *pre; stuct list_node *next; ElemTy ...
- linux内核中链表代码分析---list.h头文件分析(二)【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...
- (笔记)Linux内核中内存相关的操作函数
linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...
随机推荐
- 注解(Annotation)
注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是 ...
- NodeJs笔记 : express框架创建工程 ----- 路由设计
一.搭建工程 1 .安装 express-generator $ npm install -g express-generator 2 .本地创建express项目 $ express -e blog ...
- WinPE引导硬盘安装64位的Windows_Server_2008系统
用 U盘WinPE引导实现硬盘安装Windows Server 2008 R2系统的方法如果想不用光盘(光盘和光驱总是靠不住的),只用U盘或移动硬盘上的WinPE引导,在电脑硬盘安装一个64位的Win ...
- arcgis api for javascript 添加图层时设置标注,自定义符号
<!DOCTYPE html> <html> <head> <meta charset="gb2312"> <meta nam ...
- QString字符串中双引号的梗
[1]QString字符串不支持双引号 最近做项目(本地环境:WIN10 + QT5.9.2 + VS2017).有个需求,需要实现形如 "key="123456"&qu ...
- STL容器之set
[1]set容器 一个集合(set)是一个容器,它其中所包含的元素的值是唯一的. [2]set容器方法 (1)set构造函数.插入函数.遍历过程 应用示例代码如下: #include <set& ...
- importlib
Python提供了importlib包作为标准库的一部分.目的就是提供Python中import语句的实现(以及__import__函数).另外,importlib允许程序员创建他们自定义的对象,可用 ...
- sqlmap的使用
安全测试===sqlmap(壹)转载 六.优化 这些参数可以优化Sqlmap的性能. 1.一键优化 参数:-o 添加此参数相当于同时添加下列三个优化参数: --keep-alive --null- ...
- 转:【专题八】P2P编程
引言: 前面的介绍专题中有朋友向我留言说介绍下关于P2P相关的内容的,首先本人对于C#网络编程也不是什么大牛,因为能力的关系,也只能把自己的一些学习过程和自己的一些学习过程中的理解和大家分享下的,下面 ...
- centos下搭建Jenkins持续集成环境(安装jenkins)
1.安装JDK yum install -y java 2.安装jenkins 添加Jenkins库到yum库,Jenkins将从这里下载安装. 1 wget -O /etc/yum.repos.d/ ...