本文共 1786 字,大约阅读时间需要 5 分钟。
在 Linux 内核中,链表是一种双向循环链表,广泛用于数据结构的组织和操作。以下将详细介绍 chain 表的结构及其使用方法。
在内核中,链表的结构体定义为:
struct list_head { struct list_head *next, *prev;}; 每个链表成员都包含两个指针:next 和 prev。这两个指针分别指向链表的下一个和前一个成员。当链表中只有一个头节点时:
next 公式指针指向自己。prev 公式指针也指向自己。当添加第二个成员时:
next 指针指向原链表的头节点。next 公式指向新成员。prev 公式指向新成员。例如:
head -> node1 -> node2 -> head
此外,内核链表是双向循环的,即最后一个节点的 next 指针指向链表的头节点。
链表在内核中的使用通常与数据结构体配合使用。具体步骤如下:
定义链表结构体:在链表节点外定义一个包含链表结构体的数据结构。
struct app_info { int app_id; int up_flow; int down_flow; struct list_head app_info_node;};初始化链表:使用 INIT_LIST_HEAD 宏初始化链表头节点。
struct list_head *head = &app_info_list->app_info_node;INIT_LIST_HEAD(head);
插入新节点:使用 list_add_tail 和 list_add 函数分别在链表头或尾部插入新节点。
list_add_tail(&app1->app_info_node, head);
获取节点结构体:使用 list_entry 宏从链表节点获取对应的数据结构体。
temp_app = list_entry(&app3->app_info_node, app_info, app_info_node);
container_of 和 list_entry 的使用container_of 和 list_entry 宏用于将链表节点转换为相应的数据结构体,前者用于获取 (container_of) 链表节点的父结构体,后者用于获取完整的结构体信息。
这两个宏的实现原理如下:
#define-offs (type, member)container_of(ptr, type, member) { const typeof( (type*)0-> member ) * __mptr = (ptr); (type *) ( (char *) __mptr - offsetof(type, member) );}list_entry(ptr, type, member) { return container_of(ptr, type, member);} container_of:获取一个链表节点的父结构体。
ptr 获取链表节点 member 的地址。member 的类型并赋值给 __mptr。list_entry:获取含有链表节点的完整数据结构体。
在内核中,链表广泛应用于以下场景:
每个链表成员都可以携带任意类型的数据,只要结构体定义明确即可。
在实际使用中,可以通过以下方式优化链表性能:
此外,可以结合 container_of 和 list_entry 等宏,实现链表操作的快速迭代和修改。
通过理解和实践 chain 表的结构及使用方法,可以更好地掌握 Linux 内核开发的核心技巧。这些建议和实例可以帮助开发者更高效地编写和优化代码。
转载地址:http://gewmz.baihongyu.com/