免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 思一克
打印 上一主题 下一主题

在用户空间编程使用linux内核链表list,hlist宏定义和操作 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-05-28 20:43 |只看该作者
wow...good job

论坛徽章:
0
12 [报告]
发表于 2007-05-29 09:16 |只看该作者
原帖由 flw2 于 2007-5-28 18:48 发表

c能用stl吗?



我当然是用C++咯。。。。

论坛徽章:
0
13 [报告]
发表于 2007-05-29 09:34 |只看该作者
KERNEL中主要是效率(速度),麻烦些不怕。一些系统软件也是如此。
C++/STL不容易作到。

论坛徽章:
0
14 [报告]
发表于 2008-04-11 14:34 |只看该作者
才看到思兄这份代码,我最近也要研究一下linux里面的这些宏,不过用g++编译的时候会报一些错误,虽然用C++的人使用这种宏的可能性不大,不过还是尽量做的完美一些好了,我做了一些修改:


  1. #ifndef _LINUX_LIST_H
  2. #define _LINUX_LIST_H

  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif /* __cplusplus */

  6. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

  7. #define container_of(ptr, type, member) ( { \
  8.         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  9.         (type *)( (char *)__mptr - offsetof(type,member) ); } )

  10. static inline void prefetch(const void *x) {;}
  11. static inline void prefetchw(const void *x) {;}

  12. #define LIST_POISON1  ((void *) 0x00100100)
  13. #define LIST_POISON2  ((void *) 0x00200200)

  14. struct list_head {
  15.     struct list_head *next, *prev;
  16. };

  17. #define LIST_HEAD_INIT(name) { &(name), &(name) }

  18. #define LIST_HEAD(name) \
  19.     struct list_head name = LIST_HEAD_INIT(name)

  20. #define INIT_LIST_HEAD(ptr) do { \
  21.     (ptr)->next = (ptr); (ptr)->prev = (ptr); \
  22. } while (0)

  23. /*
  24. * * Insert a newobj entry between two known consecutive entries.
  25. * *
  26. * * This is only for internal list manipulation where we know
  27. * * the prev/next entries already!
  28. * */
  29. static inline void __list_add(struct list_head *newobj,
  30.         struct list_head *prev,
  31.         struct list_head *next)
  32. {
  33.     next->prev = newobj;
  34.     newobj->next = next;
  35.     newobj->prev = prev;
  36.     prev->next = newobj;
  37. }

  38. /**
  39. * * list_add - add a newobj entry
  40. * * @newobj: newobj entry to be added
  41. * * @head: list head to add it after
  42. * *
  43. * * Insert a newobj entry after the specified head.
  44. * * This is good for implementing stacks.
  45. * */
  46. static inline void list_add(struct list_head *newobj, struct list_head *head)
  47. {
  48.     __list_add(newobj, head, head->next);
  49. }

  50. /**
  51. * * list_add_tail - add a newobj entry
  52. * * @newobj: newobj entry to be added
  53. * * @head: list head to add it before
  54. * *
  55. * * Insert a newobj entry before the specified head.
  56. * * This is useful for implementing queues.
  57. * */
  58. static inline void list_add_tail(struct list_head *newobj, struct list_head *head)
  59. {
  60.     __list_add(newobj, head->prev, head);
  61. }

  62. static inline void __list_del(struct list_head * prev, struct list_head * next)
  63. {
  64.     next->prev = prev;
  65.     prev->next = next;
  66. }

  67. static inline void list_del(struct list_head *entry)
  68. {
  69.     __list_del(entry->prev, entry->next);
  70.     entry->next = (struct list_head*)LIST_POISON1;
  71.     entry->prev = (struct list_head*)LIST_POISON2;
  72. }

  73. static inline void list_del_init(struct list_head *entry)
  74. {
  75.     __list_del(entry->prev, entry->next);
  76.     INIT_LIST_HEAD(entry);
  77. }

  78. static inline void list_move(struct list_head *list, struct list_head *head)
  79. {
  80.     __list_del(list->prev, list->next);
  81.     list_add(list, head);
  82. }

  83. static inline void list_move_tail(struct list_head *list,
  84.         struct list_head *head)
  85. {
  86.     __list_del(list->prev, list->next);
  87.     list_add_tail(list, head);
  88. }

  89. static inline int list_empty(const struct list_head *head)
  90. {
  91.     return head->next == head;
  92. }

  93. static inline int list_empty_careful(const struct list_head *head)
  94. {
  95.     struct list_head *next = head->next;
  96.     return (next == head) && (next == head->prev);
  97. }

  98. static inline void __list_splice(struct list_head *list,
  99.         struct list_head *head)
  100. {
  101.     struct list_head *first = list->next;
  102.     struct list_head *last = list->prev;
  103.     struct list_head *at = head->next;

  104.     first->prev = head;
  105.     head->next = first;

  106.     last->next = at;
  107.     at->prev = last;
  108. }

  109. /**
  110. * * list_splice - join two lists
  111. * * @list: the newobj list to add.
  112. * * @head: the place to add it in the first list.
  113. * */
  114. static inline void list_splice(struct list_head *list, struct list_head *head)
  115. {
  116.     if (!list_empty(list))
  117.         __list_splice(list, head);
  118. }

  119. /**
  120. * * list_splice_init - join two lists and reinitialise the emptied list.
  121. * * @list: the newobj list to add.
  122. * * @head: the place to add it in the first list.
  123. * *
  124. * * The list at @list is reinitialised
  125. * */
  126. static inline void list_splice_init(struct list_head *list,
  127.         struct list_head *head)
  128. {
  129.     if (!list_empty(list)) {
  130.         __list_splice(list, head);
  131.         INIT_LIST_HEAD(list);
  132.     }
  133. }

  134. #define list_entry(ptr, type, member) container_of(ptr, type, member)


  135. #define list_for_each(pos, head) \
  136.     for (pos = (head)->next; prefetch(pos->next), pos != (head); \
  137.             pos = pos->next)

  138. #define __list_for_each(pos, head) \
  139.     for (pos = (head)->next; pos != (head); pos = pos->next)

  140. #define list_for_each_prev(pos, head) \
  141.     for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
  142.             pos = pos->prev)

  143. #define list_for_each_safe(pos, n, head) \
  144.     for (pos = (head)->next, n = pos->next; pos != (head); \
  145.             pos = n, n = pos->next)

  146. #define list_for_each_entry(pos, head, member)                                \
  147.     for (pos = list_entry((head)->next, typeof(*pos), member);        \
  148.             prefetch(pos->member.next), &pos->member != (head);         \
  149.             pos = list_entry(pos->member.next, typeof(*pos), member))

  150. #define list_for_each_entry_reverse(pos, head, member)                        \
  151.     for (pos = list_entry((head)->prev, typeof(*pos), member);        \
  152.             prefetch(pos->member.prev), &pos->member != (head);         \
  153.             pos = list_entry(pos->member.prev, typeof(*pos), member))

  154. #define list_prepare_entry(pos, head, member) \
  155.     ((pos) ? : list_entry(head, typeof(*pos), member))

  156. #define list_for_each_entry_continue(pos, head, member)                 \
  157.     for (pos = list_entry(pos->member.next, typeof(*pos), member);        \
  158.             prefetch(pos->member.next), &pos->member != (head);        \
  159.             pos = list_entry(pos->member.next, typeof(*pos), member))

  160. #define list_for_each_entry_safe(pos, n, head, member)                        \
  161.     for (pos = list_entry((head)->next, typeof(*pos), member),        \
  162.             n = list_entry(pos->member.next, typeof(*pos), member);        \
  163.             &pos->member != (head);                                         \
  164.             pos = n, n = list_entry(n->member.next, typeof(*n), member))

  165. //HASH LIST
  166. struct hlist_head {
  167.     struct hlist_node *first;
  168. };

  169. struct hlist_node {
  170.     struct hlist_node *next, **pprev;
  171. };

  172. #define HLIST_HEAD_INIT { .first = NULL }
  173. #define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
  174. #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
  175. #define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)

  176. static inline int hlist_unhashed(const struct hlist_node *h)
  177. {
  178.     return !h->pprev;
  179. }

  180. static inline int hlist_empty(const struct hlist_head *h)
  181. {
  182.     return !h->first;
  183. }

  184. static inline void __hlist_del(struct hlist_node *n)
  185. {
  186.     struct hlist_node *next = n->next;
  187.     struct hlist_node **pprev = n->pprev;
  188.     *pprev = next;
  189.     if (next)
  190.         next->pprev = pprev;
  191. }

  192. static inline void hlist_del(struct hlist_node *n)
  193. {
  194.     __hlist_del(n);
  195.     n->next = (struct hlist_node*)LIST_POISON1;
  196.     n->pprev = (struct hlist_node**)LIST_POISON2;
  197. }

  198. static inline void hlist_del_init(struct hlist_node *n)
  199. {
  200.     if (n->pprev)  {
  201.         __hlist_del(n);
  202.         INIT_HLIST_NODE(n);
  203.     }
  204. }

  205. static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
  206. {
  207.     struct hlist_node *first = h->first;
  208.     n->next = first;
  209.     if (first)
  210.         first->pprev = &n->next;
  211.     h->first = n;
  212.     n->pprev = &h->first;
  213. }


  214. /* next must be != NULL */
  215. static inline void hlist_add_before(struct hlist_node *n,
  216.         struct hlist_node *next)
  217. {
  218.     n->pprev = next->pprev;
  219.     n->next = next;
  220.     next->pprev = &n->next;
  221.     *(n->pprev) = n;
  222. }

  223. static inline void hlist_add_after(struct hlist_node *n,
  224.         struct hlist_node *next)
  225. {
  226.     next->next = n->next;
  227.     n->next = next;
  228.     next->pprev = &n->next;

  229.     if(next->next)
  230.         next->next->pprev  = &next->next;
  231. }

  232. #define hlist_entry(ptr, type, member) container_of(ptr,type,member)

  233. #define hlist_for_each(pos, head) \
  234.     for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
  235.             pos = pos->next)

  236. #define hlist_for_each_safe(pos, n, head) \
  237.     for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
  238.             pos = n)

  239. #define hlist_for_each_entry(tpos, pos, head, member)                         \
  240.     for (pos = (head)->first;                                         \
  241.             pos && ({ prefetch(pos->next); 1;}) &&                         \
  242.             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
  243.             pos = pos->next)

  244. #define hlist_for_each_entry_continue(tpos, pos, member)                 \
  245.     for (pos = (pos)->next;                                                 \
  246.             pos && ({ prefetch(pos->next); 1;}) &&                         \
  247.             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
  248.             pos = pos->next)

  249. #define hlist_for_each_entry_from(tpos, pos, member)                         \
  250.     for (; pos && ({ prefetch(pos->next); 1;}) &&                         \
  251.             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
  252.             pos = pos->next)

  253. #define hlist_for_each_entry_safe(tpos, pos, n, head, member)                  \
  254.     for (pos = (head)->first;                                         \
  255.             pos && ({ n = pos->next; 1; }) &&                                  \
  256.             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
  257.             pos = n)

  258. #ifdef __cplusplus
  259. }
  260. #endif /* __cplusplus */

  261. #endif

复制代码

论坛徽章:
0
15 [报告]
发表于 2008-04-11 14:47 |只看该作者

论坛徽章:
0
16 [报告]
发表于 2008-04-11 15:49 |只看该作者
看了一下 这些宏的设计很巧妙 但是用了一些gcc的扩展 比如typeof  这样要移植到别的编译器可能有一些问题  折中的办法是使用者自己传入类型替代这个宏.

论坛徽章:
0
17 [报告]
发表于 2008-04-11 15:53 |只看该作者
比如container_of宏的改造:

#define container_of(ptr, type, member) ( { \
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
        (type *)( (char *)__mptr - offsetof(type,member) ); } )
变为:
#define container_of2(ptr, ptrtype, type, member) ( { \
        const ptrtype *__mptr = (ptr); \
        (type *)( (char *)__mptr - offsetof(type,member) ); } )

论坛徽章:
0
18 [报告]
发表于 2008-04-11 16:21 |只看该作者
LINUX代码非常巧妙, 还有许多比如树操作, 也是类似的宏+代码, 也可以在应用程序中使用.

原帖由 converse 于 2008-4-11 15:53 发表
比如container_of宏的改造:

#define container_of(ptr, type, member) ( { \
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
        (type *)( (char *)__mptr - offsetof(type,memb ...

论坛徽章:
0
19 [报告]
发表于 2008-04-11 17:16 |只看该作者
原帖由 converse 于 2008-4-11 15:53 发表
比如container_of宏的改造:

#define container_of(ptr, type, member) ( { \
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
        (type *)( (char *)__mptr - offsetof(type,memb ...


为什么不变为:

  1. #define container_of2(ptr, type, member) ( { \
  2.         (type *)( (char *)(ptr) - offsetof(type,member) ); } )
复制代码


上面的代码,该用typeof定义变量的时候不用,比如list_for_each_entry里的head
不该用typeof的时候却用了,比如这个container_of

论坛徽章:
0
20 [报告]
发表于 2008-05-10 18:38 |只看该作者
这个list.h在非linux系统中使用不会有问题吧?

#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200200)

这两个定义的作用是什么呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP