LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2538|回复: 4

如何使用内核提供的双向循环列表

[复制链接]
发表于 2007-8-29 16:28:38 | 显示全部楼层 |阅读模式
我从include/linux/list.h中提取出了关于双向循环链表的核心部分,并以此为基础加上一个例子展示一下这个非常有用的功能。
list功能的头文件:
  1. /*********************************************************************************************************/
  2. //Author:                  Tang Xu
  3. //File:                  list_fun.h
  4. //
  5. /*********************************************************************************************************/
  6. #ifndef LIST_FUN_H
  7. #define LIST_FUN_H
  8. #define LIST_HEAD_INIT(name) { &(name), &(name) }
  9. #define LIST_HEAD(name) \
  10.         struct list_head name = LIST_HEAD_INIT(name)
  11. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  12. /**
  13. * container_of - cast a member of a structure out to the containing structure
  14. * @ptr:        the pointer to the member.
  15. * @type:        the type of the container struct this is embedded in.
  16. * @member:        the name of the member within the struct.
  17. *
  18. */
  19. #define container_of(ptr, type, member) ({                        \
  20.         const typeof( ((type *)0)->member ) *__mptr = (ptr);        \
  21.         (type *)( (char *)__mptr - offsetof(type,member) );})
  22. /**
  23. * list_entry - get the struct for this entry
  24. * @ptr:        the &struct list_head pointer.
  25. * @type:        the type of the struct this is embedded in.
  26. * @member:        the name of the list_struct within the struct.
  27. */
  28. #define list_entry(ptr, type, member) \
  29.         container_of(ptr, type, member)
  30. /**
  31. * list_for_each        -        iterate over a list
  32. * @pos:        the &struct list_head to use as a loop counter.
  33. * @head:        the head for your list.
  34. */       
  35. #define list_for_each(pos, head) \
  36.         for (pos = (head)->next; pos != (head); pos = pos->next)
  37. #define list_for_each_prev(pos, head) \
  38.         for (pos = (head)->prev; pos != (head); pos = pos->prev)
  39.        
  40. /**
  41. * list_for_each_entry        -        iterate over list of given type
  42. * @pos:        the type * to use as a loop counter.
  43. * @head:        the head for your list.
  44. * @member:        the name of the list_struct within the struct.
  45. */
  46. #define list_for_each_entry(pos, head, member)                                \
  47.         for (pos = list_entry((head)->next, typeof(*pos), member);        \
  48.              &pos->member != (head);         \
  49.              pos = list_entry(pos->member.next, typeof(*pos), member))
  50. #define list_for_each_entry_reverse(pos, head, member)                        \
  51.         for (pos = list_entry((head)->prev, typeof(*pos), member);        \
  52.              &pos->member != (head);         \
  53.              pos = list_entry(pos->member.prev, typeof(*pos), member))       
  54.                  
  55. struct list_head {
  56.         struct list_head *next, *prev;
  57. };
  58. #ifdef __cplusplus
  59. extern "C" {
  60. #endif
  61. /**
  62. *
  63. */
  64. extern void INIT_LIST_HEAD(struct list_head *list);
  65. /**
  66. *
  67. */
  68. extern void list_add(struct list_head *new, struct list_head *head);
  69. /**
  70. *
  71. */
  72. extern void list_add_tail(struct list_head *new, struct list_head *head);
  73. /**
  74. *
  75. */
  76. extern void list_del(struct list_head *entry);
  77. /**
  78. *
  79. */
  80. extern int list_empty(const struct list_head *head);
  81. /**
  82. *
  83. */
  84. extern void list_del_init(struct list_head *entry);
  85. #ifdef __cplusplus
  86. }
  87. #endif
  88. #endif
复制代码

下面是实现该功能的文件。
  1. #include "list_fun.h"
  2. #define LIST_POISON1  ((void *) 0x00100100)
  3. #define LIST_POISON2  ((void *) 0x00200200)
  4.        
  5. void INIT_LIST_HEAD(struct list_head *list)
  6. {
  7.         list->next = list;
  8.         list->prev = list;
  9. }
  10. void __list_add(struct list_head *new,
  11.                               struct list_head *prev,
  12.                               struct list_head *next)
  13. {
  14.         next->prev = new;
  15.         new->next = next;
  16.         new->prev = prev;
  17.         prev->next = new;
  18. }
  19. void list_add(struct list_head *new, struct list_head *head)
  20. {
  21.         __list_add(new, head, head->next);
  22. }
  23. void list_add_tail(struct list_head *new, struct list_head *head)
  24. {
  25.         __list_add(new, head->prev, head);
  26. }
  27. void __list_del(struct list_head * prev, struct list_head * next)
  28. {
  29.         next->prev = prev;
  30.         prev->next = next;
  31. }
  32. void list_del(struct list_head *entry)
  33. {
  34.         __list_del(entry->prev, entry->next);
  35.         entry->next = LIST_POISON1;
  36.         entry->prev = LIST_POISON2;
  37. }
  38. int list_empty(const struct list_head *head)
  39. {
  40.         return head->next == head;
  41. }
  42. void list_del_init(struct list_head *entry)
  43. {
  44.         __list_del(entry->prev, entry->next);
  45.         INIT_LIST_HEAD(entry);
  46. }
复制代码

再下面是如何使用的参考代码。
  1. #include <stdio.h>
  2. #include "list_fun.h"
  3. typedef struct _test {
  4.         struct list_head list;
  5.         void * data;
  6.         int           len;
  7. } TESTLIST;
  8. int main()
  9. {
  10.         int i;
  11.         TESTLIST head;
  12.         memset( &head, 0, sizeof( TESTLIST));
  13.         INIT_LIST_HEAD( &head.list);
  14.         //创建链表
  15.         TESTLIST * p_testlist = NULL;
  16.         for( i=0; i<100; i++) {
  17.                 p_testlist = malloc( sizeof( TESTLIST));
  18.                 if( NULL == p_testlist) {
  19.                         perror("Memory shortage");
  20.                         exit( -1);
  21.                 }
  22.                 p_testlist->data = NULL;
  23.                 p_testlist->len = i;
  24.                 list_add( &p_testlist->list, &head.list);
  25.         }
  26.         //遍历链表并打印
  27.         p_testlist = NULL;
  28.         list_for_each_entry( p_testlist, &head.list, list)
  29.                 printf("%d\n", p_testlist->len);
  30.         //删除链表
  31.         p_testlist = NULL;
  32.         list_for_each_entry( p_testlist, &head.list, list) {
  33.                 list_del( &p_testlist->list);
  34.              if( p_testlist->data) {
  35.                    free( p_testlist->data);
  36.               }
  37.               free( p_testlist);
  38.        }
  39.         return 0;
  40. }
复制代码
发表于 2007-8-30 09:23:23 | 显示全部楼层
运行结果是Segmentation fault
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-8-30 11:32:49 | 显示全部楼层
删除链表那里有些问题,不好意思。改成
       
  1. //删除链表
  2.         p_testlist = NULL;
  3.         struct list_head * j;
  4.         list_for_each( j, &head.list) {
  5.                 struct list_head tmp;
  6.                 tmp.next = j->next;
  7.                 tmp.prev = j->prev;               
  8.                 if( list_entry( j, TESTLIST, list)->data )
  9.                         free( list_entry( j, TESTLIST, list)->data);
  10.                 list_del( j);
  11.                 free( list_entry( j, TESTLIST, list));
  12.                 j = &tmp;
  13.         }
复制代码
回复 支持 反对

使用道具 举报

发表于 2008-1-15 10:20:53 | 显示全部楼层
为什么要加上这么一段?
  1.                 struct list_head tmp;
  2.                 tmp.next = j->next;
  3.                 tmp.prev = j->prev;               
  4.                 j = &tmp;
复制代码
回复 支持 反对

使用道具 举报

发表于 2008-5-14 11:31:02 | 显示全部楼层
好东西,问一下内核里的哈希表数据结构在哪个文件有实现的呀?能提供一些使用的例子代码吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表