struct list_head { struct list_head *next , *prev ; };
双向循环链表。没有设计数据域,通用性和灵活性更好。
实际使用时,构成如下:
struct user_list { void * data; struct list_head list ; }
初始化设计:
#define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT (name )
添加元素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static inline void __list_add(struct list_head *new , struct list_head *prev, struct list_head *next) { next->prev = new ; new ->next = next; new ->prev = prev; prev->next = new ; }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); }
删除元素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; }#define LIST_POISON1 ((void *) 0x00100100) #define LIST_POISON2 ((void *) 0x00200200) static inline void list_del (struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
通过 list_head 成员,找到整个结构体的地址:
#define list_entry(ptr, type, member) \ ( \ (type*) \ ( \ (char *)(ptr) - \ (unsigned long )( &((type*)0 )->member ) \ ) \ )
type是包含 list_head 类型成员的自定义结构体,ptr 是 list_head ,指向
member 成员。 (unsigned long)( &((type*)0)->member ):从 0
地址定义的一个结构,得到 member 成员的偏移量。ptr
进行偏移之后,得到自定义结构体的地址。
遍历节点:
#define __list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next)
safe版本保存了临时的 next 节点,即使 pos 被删除了,也能通过 n 找到
next 节点。
更常用的类似 list_entry 是 container_of。