/ ********************& 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;成员);