本文共 2031 字,大约阅读时间需要 6 分钟。
首先找到list_head 结构体定义,kernel/inclue/linux/types.h 如下:
struct list_head { struct list_head *next, *prev;};然后就开始围绕这个结构开始构建链表,然后插入、删除节点 ,遍历整个链表等等,其实内核已经提供好了现成的接口,接下来就让我们进入 kernel/include/linux/list.h中:
1、利用2个宏实现链表头创建#define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)2、函数实现static inline void INIT_LIST_HEAD(struct list_head *list){ WRITE_ONCE(list->next, list); list->prev = list;}#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val))//volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
初始化有数据的链表={数据+链表指针结构}:
创建宿主结构体:struct my_task_list { int val ; struct list_head mylist;//只包含前后指针}实例比如:struct my_task_list first_task = { .val = 1; .mylist = LIST_HEAD_INIT(first_task.mylist);//宏替换};或者struct my_task_list my_second_task;my_second_task.val = 2;INIT_LIST_HEAD(&my_second_task.mylist);
list_add(struct list_head *new, struct list_head *head)
传参1:struct list_head *new待插入的链表节点 传参2:struct list_head *head在该节点后面插入新节点、 【向head节点后面插入节点】
先来的节点靠后,而后来的节点靠前,“先进后出,后进先出”。所以此种结构类似于 stack“堆栈”, 而 header_task就类似于内核stack中的栈顶指针esp, 它都是紧靠着最后push到栈的元素。
list_add_tail(struct list_head *new, struct list_head *head)
传参1:struct list_head *new待插入的链表节点 传参2:struct list_head *head在该节点前面插入新节点 【该函数类似于向链表尾部插入节点】
list_add_tail类似于队列尾部的放入节点
list_del(struct list_head *entry)//删除链表单元entry
实现: { 下一个节点的prev=prev 上一个节点的next=next }
从前向后遍历/** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)从后向前遍历/** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */#define list_for_each_prev(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev)
而且,list.h 中也提供了list_replace( 节点替换) list_move(节点移位) ,翻转,查找等接口,这里就不在一一分析了。
转载地址:http://pyhrn.baihongyu.com/