原文链接:http://blog.csdn.net/xnwyd/article/details/7359373

Linux内核链表的核心思想是:在用户自定义的结构A中声明list_head类型的成员p,这样每个结构类型为A的变量a中,都拥有同样的成员p,如下:

struct A{

int property;

struct list_head p;

}

其中,list_head结构类型定义如下:

struct list_head {

struct list_head *next,*prev;

};

list_head拥有两个指针成员,其类型都为list_head,分别为前驱指针prev和后驱指针next。

假设:

(1)多个结构类型为A的变量a1...an,其list_head结构类型的成员为p1...pn

(2)一个list_head结构类型的变量head,代表头节点

使:

(1)head.next= p1 ; head.prev = pn

(2) p1.prev = head,p1.next = p2;

(3)p2.prev= p1 , p2.next = p3;

(n)pn.prev= pn-1 , pn.next = head

以上,则构成了一个循环链表。

因p是嵌入到a中的,p与a的地址偏移量可知,又因为head的地址可知,所以每个结构类型为A的链表节点a1...an的地址也是可以计算出的,从而可实现链表的遍历,在此基础上,则可以实现链表的各种操作。

下面是从linux内核中移植出来的简单链表,list.h和list.c:

list.h:

  1. #ifndef _INIT_LIST_H_
  2. #define _INIT_LIST_H_
  3.  
  4. #ifndef offsetof
  5. /* Offset of member MEMBER in a struct of type TYPE. */
  6. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  7. #endif
  8.  
  9. struct listnode
  10. {
  11. struct listnode *next;
  12. struct listnode *prev;
  13. };
  14.  
  15. #define node_to_item(node, container, member) \
  16. (container *) (((char*) (node)) - offsetof(container, member))
  17.  
  18. #define list_declare(name) \
  19. struct listnode name = { \
  20. .next = &name, \
  21. .prev = &name, \
  22. }
  23.  
  24. #define list_for_each(node, list) \
  25. for (node = (list)->next; node != (list); node = node->next)
  26.  
  27. #define list_for_each_reverse(node, list) \
  28. for (node = (list)->prev; node != (list); node = node->prev)
  29.  
  30. void list_init(struct listnode *list);
  31. void list_add_tail(struct listnode *list, struct listnode *item);
  32. void list_remove(struct listnode *item);
  33.  
  34. #define list_empty(list) ((list) == (list)->next)
  35. #define list_head(list) ((list)->next)
  36. #define list_tail(list) ((list)->prev)
  37.  
  38. #endif

list.h

  1. #ifndef _INIT_LIST_H_
  2. #define _INIT_LIST_H_
  3.  
  4. #ifndef offsetof
  5. /* Offset of member MEMBER in a struct of type TYPE. */
  6. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  7. #endif
  8.  
  9. struct listnode
  10. {
  11. struct listnode *next;
  12. struct listnode *prev;
  13. };
  14.  
  15. #define node_to_item(node, container, member) \
  16. (container *) (((char*) (node)) - offsetof(container, member))
  17.  
  18. #define list_declare(name) \
  19. struct listnode name = { \
  20. .next = &name, \
  21. .prev = &name, \
  22. }
  23.  
  24. #define list_for_each(node, list) \
  25. for (node = (list)->next; node != (list); node = node->next)
  26.  
  27. #define list_for_each_reverse(node, list) \
  28. for (node = (list)->prev; node != (list); node = node->prev)
  29.  
  30. void list_init(struct listnode *list);
  31. void list_add_tail(struct listnode *list, struct listnode *item);
  32. void list_remove(struct listnode *item);
  33.  
  34. #define list_empty(list) ((list) == (list)->next)
  35. #define list_head(list) ((list)->next)
  36. #define list_tail(list) ((list)->prev)
  37.  
  38. #endif

list.c:

  1. #include "list.h"
  2.  
  3. void list_init(struct listnode *node)
  4. {
  5. node->next = node;
  6. node->prev = node;
  7. }
  8.  
  9. void list_add_tail(struct listnode *head, struct listnode *item)
  10. {
  11. item->next = head;
  12. item->prev = head->prev;
  13. head->prev->next = item;
  14. head->prev = item;
  15. }
  16.  
  17. void list_remove(struct listnode *item)
  18. {
  19. item->next->prev = item->prev;
  20. item->prev->next = item->next;
  21. }

list.c

  1. #include "list.h"
  2.  
  3. void list_init(struct listnode *node)
  4. {
  5. node->next = node;
  6. node->prev = node;
  7. }
  8.  
  9. void list_add_tail(struct listnode *head, struct listnode *item)
  10. {
  11. item->next = head;
  12. item->prev = head->prev;
  13. head->prev->next = item;
  14. head->prev = item;
  15. }
  16.  
  17. void list_remove(struct listnode *item)
  18. {
  19. item->next->prev = item->prev;
  20. item->prev->next = item->next;
  21. }

测试代码list_test.c:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include "list.h"
  4.  
  5. #define STUDENT_FREE_MEMORY
  6.  
  7. //声明链表节点
  8. typedef struct {
  9. int id;
  10. char *name;
  11. struct listnode _list;
  12. }student;
  13.  
  14. //遍历函数指针
  15. typedef void (*student_foreach_fun)(student *stu,void *data);
  16.  
  17. //声明链表
  18. static list_declare(student_list);
  19.  
  20. //添加节点
  21. int student_add(struct listnode *list,student *stu)
  22. {
  23. list_init(&stu->_list);
  24. list_add_tail(list,&stu->_list);
  25. return ;
  26. }
  27.  
  28. //删除节点,释放节点空间
  29. int student_del(struct listnode *list,int id)
  30. {
  31. struct listnode *node;
  32. student *stu;
  33. list_for_each(node,list){
  34. stu = node_to_item(node,student,_list);
  35. if(id == stu->id){
  36. printf("list_del, id:%d,name:%s\n",stu->id,stu->name);
  37. list_remove(node);
  38. #ifdef STUDENT_FREE_MEMORY
  39. //释放节点空间
  40. free(stu);
  41. stu = NULL;
  42. #endif
  43. return ;
  44.  
  45. }
  46.  
  47. }
  48.  
  49. return ;
  50. }
  51.  
  52. //节点遍历
  53. void student_foreach(struct listnode *list,student_foreach_fun fun,void *data)
  54. {
  55. struct listnode *node;
  56. student *stu;
  57. list_for_each(node,list){
  58. stu = node_to_item(node,student,_list);
  59. fun(stu,data);
  60. }
  61.  
  62. }
  63.  
  64. //打印节点信息
  65. void student_print(student *stu,void *data)
  66. {
  67. printf("id:%d,name:%s\n",stu->id,stu->name);
  68. }
  69.  
  70. int main()
  71. {
  72. int i,len;
  73. student *stu;
  74. char *stu_name[]={"tonny","andy","michael","leslie","john"};
  75.  
  76. len = sizeof(stu_name)/sizeof(stu_name[]);
  77. //添加节点
  78. for(i=;i<len;i++){
  79. stu = calloc(,sizeof(student));
  80. stu->id = i + ;
  81. stu->name = stu_name[i];
  82.  
  83. student_add(&student_list,stu);
  84. }
  85.  
  86. //打印所有节点
  87. student_foreach(&student_list,student_print,(void *));
  88.  
  89. //删除节点
  90. student_del(&student_list,);
  91. student_foreach(&student_list,student_print,(void *));
  92.  
  93. //删除节点
  94. student_del(&student_list,);
  95. student_foreach(&student_list,student_print,(void *));
  96.  
  97. return ;
  98.  
  99. }

list_test.c

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include "list.h"
  4.  
  5. #define STUDENT_FREE_MEMORY
  6.  
  7. //声明链表节点
  8. typedef struct {
  9. int id;
  10. char *name;
  11. struct listnode _list;
  12. }student;
  13.  
  14. //遍历函数指针
  15. typedef void (*student_foreach_fun)(student *stu,void *data);
  16.  
  17. //声明链表
  18. static list_declare(student_list);
  19.  
  20. //添加节点
  21. int student_add(struct listnode *list,student *stu)
  22. {
  23. list_init(&stu->_list);
  24. list_add_tail(list,&stu->_list);
  25. return ;
  26. }
  27.  
  28. //删除节点,释放节点空间
  29. int student_del(struct listnode *list,int id)
  30. {
  31. struct listnode *node;
  32. student *stu;
  33. list_for_each(node,list){
  34. stu = node_to_item(node,student,_list);
  35. if(id == stu->id){
  36. printf("list_del, id:%d,name:%s\n",stu->id,stu->name);
  37. list_remove(node);
  38. #ifdef STUDENT_FREE_MEMORY
  39. //释放节点空间
  40. free(stu);
  41. stu = NULL;
  42. #endif
  43. return ;
  44.  
  45. }
  46.  
  47. }
  48.  
  49. return ;
  50. }
  51.  
  52. //节点遍历
  53. void student_foreach(struct listnode *list,student_foreach_fun fun,void *data)
  54. {
  55. struct listnode *node;
  56. student *stu;
  57. list_for_each(node,list){
  58. stu = node_to_item(node,student,_list);
  59. fun(stu,data);
  60. }
  61.  
  62. }
  63.  
  64. //打印节点信息
  65. void student_print(student *stu,void *data)
  66. {
  67. printf("id:%d,name:%s\n",stu->id,stu->name);
  68. }
  69.  
  70. int main()
  71. {
  72. int i,len;
  73. student *stu;
  74. char *stu_name[]={"tonny","andy","michael","leslie","john"};
  75.  
  76. len = sizeof(stu_name)/sizeof(stu_name[]);
  77. //添加节点
  78. for(i=;i<len;i++){
  79. stu = calloc(,sizeof(student));
  80. stu->id = i + ;
  81. stu->name = stu_name[i];
  82.  
  83. student_add(&student_list,stu);
  84. }
  85.  
  86. //打印所有节点
  87. student_foreach(&student_list,student_print,(void *));
  88.  
  89. //删除节点
  90. student_del(&student_list,);
  91. student_foreach(&student_list,student_print,(void *));
  92.  
  93. //删除节点
  94. student_del(&student_list,);
  95. student_foreach(&student_list,student_print,(void *));
  96.  
  97. return ;
  98.  
  99. }

Makefile:

  1. TARGET=list_test
  2. SRC=list_test.c list.c
  3. #SRC=$(wildcard *.c)
  4. OBJ=$(SRC:.c=.o)
  5. CFLAGS=-g -Wall -o
  6.  
  7. $(TARGET):$(SRC)
  8. gcc $(SRC) $(CFLAGS) $(TARGET)
  9. clean:
  10. rm $(OBJ) $(TARGET)

Makefile

  1. TARGET=list_test
  2. SRC=list_test.c list.c
  3. #SRC=$(wildcard *.c)
  4. OBJ=$(SRC:.c=.o)
  5. CFLAGS=-g -Wall -o
  6.  
  7. $(TARGET):$(SRC)
  8. gcc $(SRC) $(CFLAGS) $(TARGET)
  9. clean:
  10. rm $(OBJ) $(TARGET)

linux内核链表使用的更多相关文章

  1. C语言 Linux内核链表(企业级链表)

    //Linux内核链表(企业级链表) #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> ...

  2. 深入分析 Linux 内核链表--转

    引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...

  3. Linux 内核链表

    一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_d ...

  4. linux内核链表分析

    一.常用的链表和内核链表的区别 1.1  常规链表结构        通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节 ...

  5. 深入分析 Linux 内核链表

    转载:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/   一. 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指 ...

  6. Linux 内核 链表 的简单模拟(2)

    接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the & ...

  7. Linux 内核 链表 的简单模拟(1)

    第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...

  8. linux内核链表的移植与使用

    一.  Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /********************* ...

  9. [国嵌攻略][108][Linux内核链表]

    链表简介 链表是一种常见的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入 ...

  10. linux内核链表的使用

    linux内核链表:链表通常包括两个域:数据域和指针域.struct list_head{struct list_head *next,*prev;};include/linux/list.h中实现了 ...

随机推荐

  1. 【转】Javascript中使用WScript.Shell对象执行.bat文件和cmd命令

    WScript.Shell(Windows Script Host Runtime Library)是一个对象,对应的文件是C:/WINDOWS/system32/wshom.ocx,Wscript. ...

  2. mysql联表更新使用join

    update TableA  as a inner join TableB as b on a.order_id=b.order_id set a.last_time='2018-01-01' whe ...

  3. Java使用默认浏览器打开指定URL的方法(二种方法)

    直接看代码:方法一: 复制代码 代码如下: Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler http://ww ...

  4. win7系统 无线上网卡 共享网络,设置成wifi热点

    给家人买了一个新的智能手机,用的移动神州行套餐,没有开通3G,想更新一些应用软件,于是想到能不能用电脑上的无线上网卡. 在网上找到了一方法,试了一下,还真是可以. 步骤如下: 用无线上网卡拨号上网,并 ...

  5. execute() 和 sumbit() 的区别

    execute()内部实现 1.首次通过workCountof()获知当前线程池中的线程数, 如果小于corePoolSize, 就通过addWorker()创建线程并执行该任务: 否则,将该任务放入 ...

  6. Centos查公网IP地址

    [root@syy ~]# curl icanhazip.com 115.29.208.111

  7. Date时间

    var date_obj= new Date(); alert(date_obj.toLocaleString()) //2017/12/26 上午1:10:54 var date_obj2= new ...

  8. The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone问题解决

    从错误即可知道是时区的错误,因此只要将时区设置为你当前系统时区即可 因此使用root用户登录mysql,按照如下图所示操作即可. 把时区设置为所在地时区(即东八区的时区)后,再连接数据库就可以了

  9. [AI]神经网络章2 神经网络中反向传播与梯度下降的基本概念

    反向传播和梯度下降这两个词,第一眼看上去似懂非懂,不明觉厉.这两个概念是整个神经网络中的重要组成部分,是和误差函数/损失函数的概念分不开的. 神经网络训练的最基本的思想就是:先“蒙”一个结果,我们叫预 ...

  10. Sort Array By Parity LT905

    Given an array A of non-negative integers, return an array consisting of all the even elements of A, ...