LIST_ENTRY链表

链表的使用
链表是驱动开发中经常遇到的一个数据结构,主要是双向循环链表;要使用链表,需要用到一个LIST_ENTRY的结构,其定义如下:

typedef struct _LIST_ENTRY {
    struct _LIST_ENTRY  *Flink;    // 指向下一个节点
    struct _LIST_ENTRY  *Blink;    // 指向前一个节点
} LIST_ENTRY, *PLIST_ENTRY;
在实际的编程中,我们需要自己定义链表的节点,并把节点的第一个成员设置为LIST_ENTRY类型的变量(不一定放在第一位,但通常是这样);此外,我们还需要一个LIST_ENTRY类型的链表头;其他的就靠下面的函数或者宏来操作了:

InitializeListHead,初始化链表头
IsListEmpty,判断链表是否为空
InsertHeadList,从链表头部插入节点
InsertTailList,从链表尾部插入节点
RemoveHeadList,从链表头部删除节点
RemoveTailList,从链表尾部删除节点
CONTAINING_RECORD,从RemoveHeadList或者RemoveTailList返回的数据获取一个指向删除节点的指针

示例代码:

 typedef struct _LIST_NODE
{
 LIST_ENTRY ListEntry;
 ULONG ulData;
} LIST_NODE, *PLIST_NODE;
 
VOID LinkListTest()
{
 LIST_ENTRY listHead;
 PLIST_NODE pListNode = NULL;
 ULONG i = 0;
 
 InitializeListHead(&listHead);
 DebugPrint(("Begin insert to link list\r\n"));
 for (i = 0; i < 10; ++i)
 {
  pListNode = (PLIST_NODE)
   ExAllocatePool(PagedPool, sizeof(LIST_NODE));
  pListNode->ulData = i;
  InsertHeadList(&listHead, &pListNode->ListEntry);
 }
 
 DebugPrint(("Begin remove from link list\r\n"));
 while (!IsListEmpty(&listHead))
 {
  PLIST_ENTRY pEntry = RemoveTailList(&listHead);
  pListNode = CONTAINING_RECORD(pEntry,
         LIST_NODE,
         ListEntry);
  DebugPrint(("Delete Node's Value: %d\r\n", pListNode->ulData));
  ExFreePool(pListNode);
 }
}

 

代码中用宏表示的:

//LIST_ENTRY的结构表头必须要用InitializeListHead初始化
NPROT_INIT_LIST_HEAD(&Globals.OpenList);

你可能感兴趣的:(内核,网络驱动)