Windows内核编程基础之使用LIST_ENTRY

    LIST_ENTRY 是一个双向链表结构。它总是在使用的时候被插入到已有的数据结构中。Windows内核中使用LIST_ENTRY作为i链表,这个结构随处可见。

    看看下面的代码,构建了一个链表,每个节点是又一个文件名和一个文件大小两个数据成员组成的结构。此外有一个FILE_OBJECT指针对象,在驱动中代表一个文件对象。该链表的作用是保存了文件的文件长度文件名

typedef struct{
	LIST_ENTRY list_Entry,
	PFILE_OBJECT file_Object,
	UNICODE_STRING file_Name,
	LARGE_INTEGER file_Length
}MY_FILE_INFO, *PMY_FILE_INFO;
        请注意:这个结构体中多了一个 LIST_ENTRY list_Entry,这样做是为了保证节点插入的位置无所谓。可以将待插入的节点放在任何位置。

        LIST_ENTRY 如果是作为链表的头,在使用之前,必须调用InitializeListHead 来初始化。比如像下面这样:

///----链表头
LIST_ENTRY my_List_Head;

///---链表头初始化,一般地应该在程序入口处调用一下
void MyFileInfoInit()
{
	InitializeListHead(&my_List_Head);
}

///---节点:文件长度和文件名
typedef struct{
	LIST_ENTRY list_Entry,
	PFILE_OBJECT file_Object,
	UNICODE_STRING file_Name,
	LARGE_INTEGER file_Length
}MY_FILE_INFO, *PMY_FILE_INFO;

///---追加一条信息。也就是增加一个链表节点,请注意file_name是外面分配的
///---内存由使用者管理,该链表不用管理它
NTSTATUS MyFileInfoAppendNode(
	PFILE_OBJECT file_Object,
	PUNICODE_STRING file_Name,
	PLARGE_INTEGER file_Length )
{
	PMY_FILE_INFO my_File_Info = (PMY_FILE_INFO)ExAllocatePoolWithTag(
	PagePool, sizeof(MY_FILE_INFO), MEM_TAG);
	if (NULL == my_File_Info)
	{
		return STATUS_INSUFFICIENT_RESOURES;
	}
	///----填写数据成员
		my_File_Info->file_Object = file_Object;
		my_File_Info->file_Name = file_Name;
		my_File_Info->file_Length = file_Length;
		
		///---插入到链表尾,请注意这里没有使用任何锁,所以这个函数不是多线程安全的,
		InsertHeadList(&my_List_Head, (PLIST_ENTRY)&my_File_Info);
		return STATUS_SUCCESS;
}
    上面的代码实现了插入。

    下面是的代码,是关于计算LIST_ENTRY结构体的所在节点的地址的一个示例。

for (p = my_List_Head.Flink; p != &my_List_Head.Flink; p = p->Flink)
{
	PMY_FILE_INFO elem = CONTAINTING_RECORD(p, MY_FILE_INFO, list_Entry);
}
    CONTAINTING_RECORED是一个 WDK中已经定义的宏,作用是通过一个 LIST_ENTRY结构的指针找到这个结构体所在的节点的指针,定义如下:

PCHAR CONTAINING_RECORD(
  [in] PCHAR Address,
  [in] TYPE  Type,
  [in] PCHAR Field
);
--------------------------------------------------------------------------

LIST_ENTRY中的数据成员Flink指向下一个LIST_ENTRY。整个链表的最后一个LIST_ENTRYFlink不是空, 而是指向头节点(我下面使用红色标记出来啦):

for (p = my_List_Head.Flink; p != &my_List_Head.Flink;p = p->Flink)

///----do something

得到LIST_ENTRY之后,要用CONTAINTING_RECORD来得到链表节点中的数据。

                                             ------摘自<[天书夜读-从汇编到Windows内核编程]> 

也加入了自己对这个概念的理解。


------------------------------接着秀 一张 模板----------------------------------

Windows内核编程基础之使用LIST_ENTRY_第1张图片

你可能感兴趣的:(windows驱动开发)