linux链表解析

struct list_head { struct list_head *next, *prev;  };

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

static inline int list_empty(const struct list_head *head) { eturn head->next == head; }

#define INIT_LIST_HEAD(ptr) do { (ptr)->next = (ptr); (ptr)->prev = (ptr); } while (0)   // 运行时初始化

static inline void list_add(struct list_head *new, struct list_head *head);  __list_add(new, head, head->next);

static inline void list_add_tail(struct list_head *new, struct list_head *head);  __list_add(new, head->prev, head);

static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) {

    next->prev = new; //(1)    new->next = next; //(2)

    new->prev = prev; //(3)    prev->next = new; //(4)

}

static inline void list_del(struct list_head *entry);

被剔除下来的entryprevnext指针分别被设为LIST_POSITION2LIST_POSITION1两个特殊值,保证不在链表中的节点项不可访问。对LIST_POSITION1LIST_POSITION2的访问都将引起页故障。

list_del_init()函数将节点从链表中解下来之后,调用LIST_INIT_HEAD()将节点置为空链状态。

 

static inline void list_move(struct list_head *list, struct list_head *head);

static inline void list_move_tail(struct list_head *list, struct list_head *head);

static inline void list_splice(struct list_head *list, struct list_head *head);

static inline void list_splice_init(struct list_head *list, struct list_head *head);                         

该函数在将list合并到head链表的基础上,调用INIT_LIST_HEAD(list)list设置为空链。

 

list_entry(ptr,type,member)宏,其ptr是指向该数据中list_head成员的指针,即存储在链表中的地址值,type是数据项类型,member则是数据项类型定义中list_head成员的变量名。

list_entry 宏作用:通过list_head成员访问到作为它的所有者的节点数据。

#define list_entry(ptr, type, member) container_of(ptr, type, member)

#define container_of(ptr, type, member) ({               \

                        const typeof( ((type *)0)->member ) *__mptr = (ptr);       \

                        (type *)( (char *)__mptr - offsetof(type,member) );})

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

typeof(t) 求变量t的类型,gcc扩展。

 

#define list_for_each(pos, head) \

    for (pos = (head)->next, prefetch(pos->next); pos != (head); \

    pos = pos->next, prefetch(pos->next))

注意:此宏必要把list_head放在数据结构第一项成员,至此,它的地址也就是结构变量的地址。

 

#define list_for_each_entry(pos, head, member)                          \

        for (pos = list_entry((head)->next, typeof(*pos), member);      \

             prefetch(pos->member.next), &pos->member != (head);        \

             pos = list_entry(pos->member.next, typeof(*pos), member))                          

list_for_each()不同,这里的pos是数据项结构指针类型,而不是(struct list_head *)

prefetch的含义是告诉cpu那些元素有可能马上就要用到,告诉cpu预取一下,提高速度。

反向遍历链表:list_for_each_prev()list_for_each_entry_reverse()

如遍历不是从链表头开始,而是从已知的某个节点pos开始,则用list_for_each_entry_continue(pos,head,member)

pos有值,则从pos开始遍历,如无则从链表头开始,专门提供了一个list_prepare_entry(pos,head,member)宏,将它的返回值作为list_for_each_entry_continue()pos参数,就可满足要求。

list_for_each_safe(pos, n, head)list_for_each_entry_safe(pos, n, head, member),要求调用者提供一个与pos同类型的指针n,在for循环中暂存pos下一个节点的地址,避免因pos节点被释放而造成的断链。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 内核中,工作队列是一种异步执行的机制,它允许内核模块或驱动程序在后台执行工作。工作队列由工作项(work item)组成,每个工作项表示一个要执行的任务。内核模块或驱动程序可以将工作项添加到工作队列中,然后由内核调度器异步执行。 工作项是通过 work_struct 结构体来表示的。work_struct 结构体定义如下: ```c struct work_struct { atomic_long_t data; struct list_head entry; work_func_t func; #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif }; ``` 其中,data 字段是一个原子长整型,用于存储工作项的状态信息。entry 字段是一个链表节点,用于将工作项添加到工作队列中。func 字段是一个指向工作项处理函数的指针,该函数将在工作项执行时被调用。 要创建一个新的工作项,可以使用 INIT_WORK 宏: ```c void INIT_WORK(struct work_struct *work, work_func_t func); ``` 其中,work 是指向要初始化的工作项的指针,func 是一个指向工作项处理函数的指针。 要将工作项添加到工作队列中,可以使用 queue_work 函数: ```c int queue_work(struct workqueue_struct *wq, struct work_struct *work); ``` 其中,wq 是指向要添加工作项的工作队列的指针,work 是指向要添加的工作项的指针。如果工作项成功添加到工作队列中,函数将返回 1,否则返回 0。 工作项处理函数的原型为: ```c typedef void (*work_func_t)(struct work_struct *work); ``` 其中,work 是指向正在处理的工作项的指针。 在处理工作项时,可以使用 container_of 宏将工作项的指针转换为包含它的结构体的指针: ```c struct my_work { struct work_struct work; int param1; char *param2; }; static void my_work_handler(struct work_struct *work) { struct my_work *my_work = container_of(work, struct my_work, work); int param1 = my_work->param1; char *param2 = my_work->param2; /* do something with param1 and param2 */ } ``` 在上面的示例中,我们定义了一个包含工作项的结构体 my_work,并在工作项处理函数中使用 container_of 宏将工作项的指针转换为 my_work 结构体的指针。然后,我们可以从 my_work 结构体中获取工作项的参数并使用它们进行处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值