简例仿写 Linux 内核链表遍历

一、测试源程序:

【 list.h 文件 】

 1 #ifndef _LIST_HEAD_
 2 #define _LIST_HEAD_
 3 
 4 /* 链表节点结构 */
 5 struct list_head {
 6     struct list_head *prev;
 7     struct list_head *next;
 8 };
 9 
10 /* 初始化链表 */
11 #define LIST_HEAD_INIT(name) \
12         {&(name), &(name)}
13 
14 /* 创建链表并初始化 */
15 #define LIST_HEAD(name) \
16         struct list_head name = LIST_HEAD_INIT(name)
17 
18 /* 得到结构体头至某成员的偏移量 */
19 #define offsetof(type, member)     \
20         ((void*)(&((type*)0)->member))
21 
22 /* 由成员地址得到结构体首地址 */
23 #define container_of(ptr, type, member)    \
24         ((type*)((void*)ptr-offsetof(type, member)))
25 
26 /* 链表中插入新节点 */
27 static inline void _list_add(struct list_head *new,
28     struct list_head *prev, struct list_head *next)
29 {
30     next->prev = new;
31     prev->next = new;
32     new->prev = prev;
33     new->next = next;
34 }
35 
36 #endif

【 list.c 文件 】

 1 #include 
 2 #include "list.h"
 3 
 4 #define list_entry(ptr, type, member)    \
 5         container_of(ptr, type, member)
 6 
 7 /* 利用 ptr 等于 head, 从而得到首个数据节点 */
 8 #define list_first_entry(ptr, type, member)    \
 9         list_entry((ptr)->next, type, member)
10 
11 /* 遍历整个链表, 得到第个数据节点的结构体基址 */
12 #define list_for_each_entry(entry, head, member)\
13     for(entry=list_first_entry(head,typeof(*entry),member);            \
14         &(entry)->member!=head;                                        \
15         entry=list_entry((entry)->member.next,typeof(*entry),member))
16 
17 /* 自定义三个测试变量 */
18 struct student_info {
19     char *name;
20     struct list_head list;
21 }xiaoming, xiaoqing, xiaoling;
22 
23 /* 从尾部插入新的数据节点 */
24 void list_add_tail(struct list_head *new,
25     struct list_head *head)
26 {
27     _list_add(new, head->prev, head);
28 }
29 
30 /* 创建链表并初始化 */
31 static LIST_HEAD(info_list);
32 
33 int main()
34 {
35     struct student_info *info = NULL;
36 
37     /* 初始化成员信息 */
38     xiaoming.name = "xiao_ming";
39     xiaoqing.name = "xiao_qing";
40     xiaoling.name = "xiao_ling";
41     
42     /* 插入链表 */
43     list_add_tail(&xiaoming.list, &info_list);
44     list_add_tail(&xiaoqing.list, &info_list);
45     list_add_tail(&xiaoling.list, &info_list);
46 
47     /* 遍历测试 */
48     list_for_each_entry(info, &info_list, list)
49         puts(info->name);
50 
51     return 0;
52 }

 

二、运行结果:

$ ./a.out
xiao_ming
xiao_qing
xiao_ling

 

你可能感兴趣的:(简例仿写 Linux 内核链表遍历)