LIST_ENTRY的介绍以及简单实用(未完待续)

本文介绍了在驱动开发中常用的双向循环链表数据结构,重点讲解了WDK提供的LIST_ENTRY结构体。LIST_ENTRY包含前后节点指针,实际编程中需要结合自定义节点使用。文章列举了如何自定义节点并将其与LIST_ENTRY结合,同时提到了初始化链表、插入删除节点等操作的相关函数和宏。
摘要由CSDN通过智能技术生成

  链表是驱动开发中经常使用的数据结构,以双向循环链表为主。WDK为我们提供了一个名为LIST_ENTRY的结构体,通过它我们可以使用链表。LIST_ENTRY的定义如下:

    typedef struct _LIST_ENTRY {
    struct _LIST_ENTRY  *Flink;    // 指向下一个节点
    struct _LIST_ENTRY  *Blink;    // 指向前一个节点
    } LIST_ENTRY, *PLIST_ENTRY;

  通过定义我们发现LIST_ENTRY结构体有两个子域,分别是指向下一个和上一个节点的指针,这个和我们平时使用的循环链表的节点定义类似。

  然而实际编程中仅仅依靠这个结构体是不够的,因为这个结构体中并不包含我们自己的数据。实际中我们需要自定义节点,并把该节点的一个子域(通常是第一个子域)设置为LIST_ENTRY类型的变量。举例如下:

    struct MYNODE{

    LIST_ENTRY ListEntry;

    int data;

    };

    MYNODE是我们自定义的节点,其中data是我们自己的数据,ListEntry则需要加入到由LIST_ENTRY类型变量组成的链表中。换言之,真正的链表中只包含了LIST_ENTRY类型的变量,通过链表找到特定的LIST_ENTRY变量,再获得包含这个变量的我们自定义的节点,进而获得该节点中的data数据。

    我们需要一个LIST_ENTRY类型的链表头,然后利用WDK为我们定义好的函数或者宏来进行后续操作:

    InitializeListHead,初始化链表头 
    IsListEmpty,判断链表是否为空 
    InsertHeadList,从链表头部插入节点 
    InsertTailList,从链表尾部插入节点 
    RemoveHeadList,从链表头部删除节点 
    RemoveTailList,从链表尾部删除节点 
    CONTAINING_RECORD,由指向LIST_ENTRY类型的指针获得指向自定义节点的指针(例如上面举例的指向MYNODE类型的指针)

`list_for_each_entry` 是 Linux 内核中用于遍历双向链表的宏,它可以在链表中遍历每个节点,并且可以访问每个节点的成员。 它的语法如下: ``` list_for_each_entry(pos, head, member) ``` 其中,`pos` 是遍历链表时当前节点的指针,`head` 是链表头指针,`member` 是链表节点中指向下一个节点的成员指针。 下面是一个示例: ```c #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include "list.h" struct student { char name[20]; int age; struct list_head list; }; int main() { struct student *stu1, *stu2, *stu3; struct student *pos; struct list_head *head; int i; // 初始化链表头 head = (struct list_head *)malloc(sizeof(struct list_head)); INIT_LIST_HEAD(head); // 添加节点到链表 stu1 = (struct student *)malloc(sizeof(struct student)); strcpy(stu1->name, "Tom"); stu1->age = 18; list_add_tail(&stu1->list, head); stu2 = (struct student *)malloc(sizeof(struct student)); strcpy(stu2->name, "Jerry"); stu2->age = 20; list_add_tail(&stu2->list, head); stu3 = (struct student *)malloc(sizeof(struct student)); strcpy(stu3->name, "Mike"); stu3->age = 22; list_add_tail(&stu3->list, head); // 遍历链表 printf("遍历链表:\n"); list_for_each_entry(pos, head, list) { printf("name: %s, age: %d\n", pos->name, pos->age); } // 释放节点 list_for_each_entry(pos, head, list) { list_del(&pos->list); free(pos); } // 释放链表头 free(head); return 0; } ``` 输出结果: ``` 遍历链表: name: Tom, age: 18 name: Jerry, age: 20 name: Mike, age: 22 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值