[内核驱动] 链表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) ...
随机推荐
- SignalR WebSocket Error during WebSocket handshake: net::ERR_CONNECTION_RESET
system.web 节点添加: <httpRuntime maxRequestLength="104857600" executionTimeout="1200& ...
- 「美团外卖APP签约快捷支付」流程体验
§1 添加银行卡 新用户在美团外卖APP订餐支付时,首先要绑定银行卡.如下是“添加银行卡”页,输入卡号后,系统自动调用卡bin库校验卡号的有效性,如果有效会显示发卡行和卡类型(借记卡/贷记卡). 这 ...
- LeetCode110.平衡二叉树
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1. 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 3 / \ 9 20 / \ 15 7 返回 true . 示例 ...
- import caffe报错问题
在搭建好的caffe环境下运行Python报错:ImportError:No module named _caffe 报错原因:由于caffe的Python环境变量未配置好 解决方案: 方法1 imp ...
- JSP—简介
BS/CS的区别? CS模式: client:客户端:存放操作界面的图片样式本地数据和缓存等 server:服务端:保存核心数据 请求响应模式:收到请求后,服务器只需要返回核心的数据 优缺点:需要安装 ...
- 学习笔记<3>View接触
一.View基本概念 1.界面上显示所有的控件都是用对象表示的,即有类,这些类都是View的子类. 2.View的种类 二.在Activity当中获取代表View的对象 1.根据ID可以用方法获取到对 ...
- 鼠标移动上去,元素旋转;web前端鼠标经过图片凸起
.trans-rotate{ -webkit-transition: transform .25s linear; -moz-transition: transform .25s linear; -o ...
- steam Depot 生成与应用脚本
Depot 生成脚本 首先为您上传的每个 Depot 创建一个 Depot 生成脚本.从复制 depot_build_1001.vdf 脚本开始,并按将上传的 Depot ID 命名. Depot 生 ...
- php aes128加密
//[加密数据]AES 128 ECB模式 public function aesEncrypt($str){ $screct_key = Yii::$app->params['encryptK ...
- codeforces 979C Kuro and Walking Route
题意: 给出一棵树,其中有两个点,x和y,限制走了x之后的路径上不能有y,问可以走的路径(u,v)有多少条,(u,v)和(v,u)考虑为两条不同的路径. 思路: 简单树形dp,dfs统计在x到y路径( ...