欢迎来到我司Viking代理产品网站!
使用Linux内核的链表
Viking代理 2025-05-01

/ ********************& nbsp; *链表在内核中的应用& nbsp; ************** ***** * /(1)介绍在Linux内核中使用大量链接列表结构来组织数据,包括各种功能模块中的设备列表和数据组织。

这些链表中的大多数都使用在include / linux / list.h中实现的非常棒的链表数据结构。

链接列表数据结构的定义非常简单:struct list_head { struct list_head * next,* prev; }; list_head结构包含两个指向list_head结构的指针:prev和next。

内核的数据结构通常组织成一个双循环链表。

与先前引入的双链列表结构模型不同,此处的list_head没有数据字段。

在Linux内核链接列表中,数据不包含在链接列表结构中,但是链接列表节点包含在数据结构中。

例如:struct my_struct {& nbsp; struct list_head list; & nbsp;无签名的长狗; & nbsp;无效* cat; }; Linux中的链表没有固定的标头,可以从任何元素访问它。

遍历链表仅需要从某个节点开始,然后按照指针访问下一个节点,直到它再次返回到原​​始节点为止。

每个独立的节点都可以称为链表的头。

(2)链表的初始化a。

静态地,如果链表是在编译时静态创建并直接引用的,则如下所示:struct my_struct mine = {& nbsp; .lost = LIST_HEAD_INIT(mine.list); & nbsp; .dog = 0, .cat = NULL};或静态LIST_HEAD(fox); / *等于struct list_head fox = LIST_HEAD_INIT(fox); * / b。

动态结构my_struct * p; p = kmalloc(GFP_KERNEL,sizeof(my_struct)); p-dog = 0; p-> cat = NULL; INIT_LIST_HEAD(& p-& gt; list); (3)操作链表内核提供了一组操作链表的功能。

笔记!这些函数都使用一个或多个list_head结构指针作为参数。

在& lt; linux / list.h& gt;中定义一种。

添加节点list_add(struct list_head * new,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * head);在指定链接列表的头节点之后插入新节点; & nbsp; & nbsp; & nbsp; & nbsp;& nbsp; b。

将节点添加到链接列表list_add_tail(struct list_head * new,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * head)的末尾;到指定链接列表的头节点。

将新节点插入front& nbsp;中。

& nbsp; & nbsp; & nbsp; & nbsp;& nbsp; C。

从链表list_del(struct list_head * entry)中删除一个节点;从链接列表中删除条目d。

将节点从一个链接列表移动到另一个链接列表list_move(struct list_head * list,& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * head);从链接列表中删除列表项,然后将其插入到标题e.list_empty(struct list_head * head);之后;如果链接列表为空,则返回一个非零值,否则它将返回0。

合并链接列表list_splice(struct list_head * list,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * head);注意力!新的链表不包括链表节点(4)。

遍历链表本身并不重要。

重要的是访问包含链接列表的结构。

一种。

从链接列表指针list_entry(struct list_head * ptr,& nbsp;& nbsp;& nbsp;& nbsp; type_of_struct,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; field_name); ptr:list_head指针type_of_struct:包含ptr的结构的类型field_name:结构中链接列表字段的名称。

b。

遍历链接列表list_for_each(struct list_head * cursor,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * list);常和list_entry注意配套使用!使用list_for_each遍历时,不包括头节点。

C。

遍历时,获取大结构指针list_for_each_entry(类型* cursor,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * list,& nbsp ;& nbsp;& nbsp;& nbsp;& nbsp;成员); d。

在遍历链表时,释放每个遍历的节点list_for_each_entry_safe(类型* cursor,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;类型* tmp;& nbsp;& nbsp;& nbsp;& nbsp; struct list_head * list,& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;成员);