驱动链表(LIST_ENTRY)

Posted 刘收获

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了驱动链表(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");
}

  

 

以上是关于驱动链表(LIST_ENTRY)的主要内容,如果未能解决你的问题,请参考以下文章

Ring0 - 链表

链表之LIST

链表之LIST

链表之LIST

x64驱动 遍历驱动模块

LIST_ENTRY 已损坏(即双重删除)。不知道为啥