驱动链表(LIST_ENTRY)

DDK提供了两种链表的数据结构,双向链表和单向链表,其定义如下:

typedef struct _LIST_ENTRY

{

struct _LIST_ENTRY *Flink;

struct _LIST_ENTRY *Blink;

} LIST_ENTRY,*PLIST_ENTRY;

typedef struct _SINGLE_LIST_ENTRY {
  struct _SINGLE_LIST_ENTRY *Next;
} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;

一.双向链表LIST_ENTRY

  这个结构不能直接存进我们要的数据,如果要把我们的数据存进链表的结构里,需要重新定义一个结构体,结构体里必须要包括一个LIST_ENTRY类型的成员,这个成员可以放在结构体里的任何位置,如:

typedef struct _list
{
       LIST_ENTRY List;
       ULONG data;
} Node,*PNode;

或者:

typedef struct _list
{
    ULONG data;

LIST_ENTRY List;
} Node,*PNode;

  在使用链表时要定义一个链表头并初始化,其类型为LIST_ENTRY,

  1.初始化链表函数为InitializeListHead(PLIST_ENTRY pListHeader);

2.插入链表函数

  InsertHeadList(

    PLIST_ENTRY pListHeader,     //链头

    PLIST_ENTRY MyListEntry);    //结构体中的LIST_ENTRY类型的成员变量地址

  这个函数是在链表的开头插入一个结点,第一个参数是链头,第二个参数也是一个PLIST_ENTRY类型,是我们自己定义的结构体中的LIST_ENTRY类型的成员变量地址。类似的还有从尾部插入链表函数InsertTailList,参数与InsertHeadList一致。

  3.从链表删除结点

  函数RemoveTailList(PLIST_ENTRY pListHeader)把链表的最后的结点删除,返回删除的结点的指针。

  函数RemoveHeadList(PLIST_ENTRY pListHeader)把链表的第一个结点删除,返回删除的结点的指针。

一.单向链表SINGLE_LIST_ENTRY

  1.初始化链表函数为InitializeListHead(PLIST_ENTRY pListHeader),与双向链表相同。

  2.插入链表函数   

  FORCEINLINE
  VOID
  PushEntryList(                                                                                        //从头部插入,成为第一个结点
    _Inout_ PSINGLE_LIST_ENTRY ListHead,                              //链头                  
    _Inout_ __drv_aliasesMem PSINGLE_LIST_ENTRY Entry  //结构体中的LIST_ENTRY类型的成员变量地址
  )

  {

    Entry->Next = ListHead->Next;
    ListHead->Next = Entry;
    return;
  }

  

  3.从链表删除结点  

  FORCEINLINE
  PSINGLE_LIST_ENTRY
  PopEntryList(                                                                 //从链表头下一个删除节点,删除第一个结点
    _Inout_ PSINGLE_LIST_ENTRY ListHead      //链头   
  )
  {

  PSINGLE_LIST_ENTRY FirstEntry;

  FirstEntry = ListHead->Next;
  if (FirstEntry != NULL) {
  ListHead->Next = FirstEntry->Next;
  }

  return FirstEntry;
  }

//bp ListEntry!DriverEntry

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_OBJECT  DeviceObject = NULL;
	DriverObject->DriverUnload = DriverUnload;

	SeListEntry();
	SeSingleListEntry();
	return Status;
}
VOID SeListEntry()
{
	LIST_ENTRY  ListHead;
	PITEM Item = NULL;
	ULONG i = 0;
	//初始化链表
	InitializeListHead(&ListHead);
	for (i = 0; i < 10; i++)
	{
		Item = (PITEM)
			ExAllocatePool(PagedPool, sizeof(ITEM));
		Item->ItemData = i;
		InsertHeadList(&ListHead, &Item->u.ListEntry);
	}
	while (!IsListEmpty(&ListHead))
	{
		PLIST_ENTRY ListEntry = RemoveTailList(&ListHead);

		KdPrint(("%d\n", ((PITEM)ListEntry)->ItemData));
		ExFreePool((PITEM)ListEntry);
	}
}
VOID SeSingleListEntry()
{
	SINGLE_LIST_ENTRY  ListHead;
	PITEM Item = NULL;
	ULONG i = 0;
	//初始化链表
	InitializeListHead(&ListHead);
	for (i = 0; i < 10; i++)
	{
		Item = (PITEM)
			ExAllocatePool(PagedPool, sizeof(ITEM));
		Item->ItemData = i;
		PushEntryList(&ListHead, &Item->u.SingleListEntry);
	}
	while (!IsListEmpty(&ListHead))
	{
		PSINGLE_LIST_ENTRY ListEntry = PopEntryList(&ListHead);

		KdPrint(("%d\n", ((PITEM)ListEntry)->ItemData));
		ExFreePool((PITEM)ListEntry);
	}
}

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("DriverUnload()\r\n");
}

  

时间: 2024-11-09 04:59:59

驱动链表(LIST_ENTRY)的相关文章

windows内核驱动中的链表结构

windows内核驱动中的链表结构与数据结构中的链表结构在构造上有很大不同,以循环双链表为例 数据结构中的链表结构: 数据就像集装箱,可以直接放置在火车上,而节点就像每节之间的挂接装置. 内核驱动中的链表结构: 数据就像车厢,自带挂接装置(节点) 1.链表结构体不同 数据结构中的链表结构,包含有节点和数据, struct DataList{ DataType data; struct DataList* next; struct DataList* prev; }; 驱动中的链表结构,仅包含有节

如何自己写xuetr(一) 每次改变的驱动名和服务名

首先要获取驱动模块的文件名字,根据每次文件名字的不同进行生成,名字可以从链表获得: typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING Ful

linux驱动(九)platform驱动模型详解,以及基于platform驱动模型的led驱动

参考: http://blog.csdn.net/qq_28992301/article/details/52385518 http://blog.csdn.net/zoe6553/article/details/6372445 http://blog.chinaunix.net/uid-25014876-id-111745.html 1:什么是platform总线?platform总线是区别于实体总线USB. I2C.SPI .PIC总线的虚拟总线,一些usb设备选址的话需要通过USB总线来进

I2C驱动详解

I2C讲解: 在JZ2440开发板上,I2C是由两条数据线构成的SCL,SDA:SCL作为时钟总线,SDA作为数据总线:两条线上可挂载I2C设备,如:AT24C08 两条线连接ARM9 I2C控制器,通过控制来控制I2C设备的识别设备地址.读.写操作:如图所示 从中所知:I2C线上可以挂载很多个I2C设备:挂载简单,只需要一根数据线和一根时钟线就可以挂载上去,通过地址来去别每个设备的区别: I2C操作: 对I2C操作主要思想为:1.找到设备  2.进行读写操作 主要原理为: 1.发送开始信号S

platform设备驱动框架搭建分析

之前接触到的字符设备驱动是非常单纯的Linux字符设备驱动,他不具备工程中Linux驱动中的设备与驱动分离思想和设备驱动的分层思想,不具备"总线-设备-驱动"模型的概念.接下来通过分析platform设备驱动模型的搭建过程来看看Linux的设备驱动模型究竟是怎样的? platform驱动模型搭建: (1)platform核心层:为设备层和驱动层提供注册接口.为设备层和驱动层的匹配提供标准 ①搭建总线框架: 总线类结构体: struct bus_type { const char *na

Linux设备驱动模型【转】

本文转载自:http://blog.csdn.net/xiahouzuoxin/article/details/8943863 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要. linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统结构的一般性抽象描述.换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同

linux内核驱动模型

linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构成内核对象集,用kset表示,内核对象集也包含自己的内核对象,从而组成层次化的结构.2.用sysfs文件系统导出到用户空间.内核中的所有内核对象组织成树状,以对象属性为叶子.通过sysfs文件系统,将用户空间对文件的读写操作转化为对内核对象属性的显示和保存方法.从而导出内核对象信息,并提供配置接口.

SylixOS中SD驱动实现流程

1.概述 本文档以imx6实验平台为例,介绍SD设备驱动实现流程. 2.SylixOS中SD系统框架 SylixOS中SD协议栈(以下称作SD Stack)结构如图 2.1所示. 图 2.1 SD 协议栈结构 1)Host层:硬件控制器抽象层,SD控制器在不同的硬件平台上可能有不同的实现,因此需要实现具体的传输处理操作.所有的控制器驱动都向上(Core层)提供统一的操作接口.SD Stack已经提供了符合SD规范的标准控制器SDHCI驱动,在此情况下,控制器驱动的编写将更加简单.当然也可使用SP

PHY Linux 驱动

以太网 MAC(链路层)+PHY(物理层/RTL8201F,88E1111);集成型DM9000,RTL8139CP 由于网络数据传输量较大,不论是分开型还是集成型,通常会在MAC和PHY之间引入DMA,MAC和PHY之所以有分开,是因为MAC属于数字电路部分,而PHY则属于模拟部分,负责将接收到的数据传输给MAC层,MAC层将接收到的数据传输给上层协议,如IP层,IGMP层.PHY层也负责将由MAC层发送过来的数据,转换成差分信号,经过后边的变压器后送入RJ45接头的线缆中. 对应的数据格式为