代码是最好的老师,本文以代码展示为主。
要想使用内核链表,就要在结构体中包含struct list_head类型的变量,该变量将每个元素串联起来,构成一个双向链表。
struct list_head双向链表节点
struct list_head { struct list_head *next; struct list_head *prev; };链表头初始化:使用链表前,必须初始化链表头部
// 初始化链表头 #define INIT_LIST_HEAD(head) do { \ (head)->next = (head)->prev = head; \ } while (0)插入
// 在head元素后面,插入new 1. 如果head是链表头,则: 头插 2. 如果head是元素,则:在元素后,插入new (将new插入到head后面) static inline void list_add (struct list_head *new, struct list_head *head) { new->prev = head; new->next = head->next; new->prev->next = new; new->next->prev = new; } // 尾插: 1. 如果head是链表头,则:尾插 2. 如果head是元素,则:在元素前,插入new (将new插入到head前面) static inline void list_add_tail (struct list_head *new, struct list_head *head) { new->next = head; new->prev = head->prev; new->prev->next = new; new->next->prev = new; }删除
// 删除链表中的节点(不要使用,比较危险,因为old没有prev/next没设置为NULL) static inline void list_del (struct list_head *old) { old->prev->next = old->next; old->next->prev = old->prev; old->next = (void *)0xbabebabe; old->prev = (void *)0xcafecafe; } // 删除链表中的节点(推荐使用,安全) static inline void list_del_init (struct list_head *old) { old->prev->next = old->next; old->next->prev = old->prev; old->next = old; old->prev = old; }移动move
// 将元素list从表中删除,头插入链表head中/将插入到head后面 static inline void list_move (struct list_head *list, struct list_head *head) { list_del (list); list_add (list, head); } // 将元素list从表中删除,尾插入链表head中/插入到head前面 static inline void list_move_tail (struct list_head *list, struct list_head *head) { list_del (list); list_add_tail (list, head); }链表判空
/** * 判断链表是否为空 * @return 空,1;非空,0 */ static inline int list_empty (struct list_head *head) { return (head->next == head); }链表拼接
static inline void __list_splice (struct list_head *list, struct list_head *head) { (list->prev)->next = (head->next); (head->next)->prev = (list->prev); (head)->next = (list->next); (list->next)->prev = (head); } /* 拼接两个链表: 1.如果新增的链表只有一个链表头就不做任何处理(因为链表头不包含数据) 2. (head 2 3) + (add 5 6) ==> (head 5 6 2 3) //抛弃链表头add */ static inline void list_splice (struct list_head *list, struct list_head *head) { if (list_empty (list)) return; __list_splice (list, head); } /* Splice moves @list to the head of the list at @head. */ static inline void list_splice_init (struct list_head *list, struct list_head *head) { if (list_empty (list)) return; __list_splice (list, head); INIT_LIST_HEAD (list); } /* Splice moves @list to the tail of the list at @head. */ static inline void list_splice_tail_init (struct list_head *list, struct list_head *head) { if (list_empty (list)) return; __list_splice (list, head->prev); INIT_LIST_HEAD (list); } static inline void __list_append (struct list_head *list, struct list_head *head) { (head->prev)->next = (list->next); (list->next)->prev = (head->prev); (head->prev) = (list->prev); (list->prev)->next = head; } static inline void list_append (struct list_head *list, struct list_head *head) { if (list_empty (list)) return; __list_append (list, head); } /* Append moves @list to the end of @head */ static inline void list_append_init (struct list_head *list, struct list_head *head) { if (list_empty (list)) return; __list_append (list, head); INIT_LIST_HEAD (list); } #define list_next(ptr, head, type, member) \ (((ptr)->member.next == head) ? NULL \ : list_entry((ptr)->member.next, type, member))获取list所处对象的地址
/** list_for_each(iter, &stu_list_head->list) { stu_node = list_entry(iter, stu_list_t, list); printf("id = %d, name = %s\n", stu_node->student->id, stu_node->student->name); } 等价于 list_for_each_entry() #define GET_LAST_NODE(set) \ list_entry(set.list.prev, typeof(df_file), slist) */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))遍历链表
#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) /** * 遍历(打印)链表 * @example * stu_list_t* entry; // 必须是结构体类型 // lhead类型:struct list_head* // list:是stu_list_t结构体中的struct list_head的member名字 list_for_each_entry(entry, lhead, list) { printf("id=%d, name=%s\n",entry->student->id, entry->student->name); } */ #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /** * 遍历(删除)链表 * @param [in] stu_list_t * pos 当前元素 * @param [in] stu_list_t * n * @param [in] list_head* head 链表的头结点 * @param [in] member stu_list_t结构体中list成员名 * @example stu_list_t* entry, * tmp; // 必须是结构体类型 // lhead类型:struct list_head* // list:是stu_list_t结构体中的struct list_head的member名字 list_for_each_entry_safe(entry, tmp, lhead, list) { // 从链表中删除节点 list_del(&entry->list); // 释放 free(entry->student); free(entry); } */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) #define list_for_each_entry_reverse(pos, head, member) \ for (pos = list_entry((head)->prev, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.prev, typeof(*pos), member)) #define list_for_each_entry_safe_reverse(pos, n, head, member) \ for (pos = list_entry((head)->prev, typeof(*pos), member), \ n = list_entry(pos->member.prev, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.prev, typeof(*n), member)) #endif /* _LLIST_H */代码中,出现 struct list_head list;,此处的 list 表示什么含义呢?
此处有2层含义:
① 在结构体中,仅仅表示该结构体能够通过list这个member,连接成一个链表 注意:该成员不需要初始化。 将结构体插入链表,本质上是将结构体中的list成员插入链表
typedef struct { int sno; struct list_head list; // 表示node_t节点可以通过list构成一个链表 } node_t; int main() { struct list_head lhead; // 作为链表头,表示一个链表 INIT_LIST_HEAD(&lhead); node_t nd; nd.sno = 100; // nd.list不用初始化 list_add(&nd.list, &lhead); }② 作为链表头,表示一个链表 注意:必须被初始化。 可以将结构体插入到该链表
#include "list.h" #include <stdio.h> #include <stdlib.h> #include <stdlib.h> typedef struct { int sno; struct list_head list; // 表示node_t节点可以通过list构成一个链表 } node_t; typedef struct { int node_cnt; struct list_head nodes_hd; // 作为链表头,表示一个链表 } bignode_t; int main() { // 1.初始化bignode_t bignode_t *bnd = malloc(sizeof(bignode_t)); bnd->node_cnt = 0; INIT_LIST_HEAD(&bnd->nodes_hd); // 2.创建node_t节点 node_t *nd = malloc(sizeof(nd)); nd->sno = 1008611; // 3.将nd插入到链表nodes_hd中 list_add(&nd->list, &bnd->nodes_hd); bnd->node_cnt++; }① ② 代码综合案例
#include "list.h" #include <stdio.h> #include <stdlib.h> #include <stdlib.h> typedef struct { int sno; struct list_head list; // 表示node_t节点可以通过list构成一个链表 } node_t; typedef struct { int node_cnt; struct list_head list; // 表示bignode_t节点可以通过list构成一个链表 struct list_head nodes_hd; // 表示链表头(在此处,该链表元素类型是node_t) } bignode_t; int main() { // 1.初始化bignode_t bignode_t *bnd = malloc(sizeof(bignode_t)); bnd->node_cnt = 0; INIT_LIST_HEAD(&bnd->nodes_hd); // 2.创建node_t节点 node_t *nd = malloc(sizeof(nd)); nd->sno = 1008611; // 3.将nd插入到链表nodes_hd中 list_add(&nd->list, &bnd->nodes_hd); bnd->node_cnt++; struct list_head bignds_hd; INIT_LIST_HEAD(&bignds_hd); list_add(&bnd->list, &bignds_hd); // bnd又作为元素,插入到bignds_hd链表中 }