QQ在线咨询
售前咨询热线
15821572819
售后咨询热线
15821572819

内核链表list.h文件剖析


内核链表list.h文件剖析

一、内核链表的结构【双向循环链表】

    内核链表的好主要体现为两点,1是可扩展性,2是封装。可以将内核链表复用到用户态编程中,以后在用户态下编程就不需要写一些关于链表的代码了,直接将内核中list.h中的代码拷贝过来用。


[cpp] view plain copy

  1. struct list_head  

  2. {  

  3.   struct list_head *next, *prev;  

  4. }; // 包含了两个指向list_head结构体的指针next,prev[后驱和前驱]  


 

二、内核链表常用接口

1、INIT_LIST_HEAD:创建链表

2、list_add:在prev和next之间插入结点

3、list_add_tail:在链表尾插入结点

4、list_del:删除结点

5、list_entry:取出结点

6、list_for_each:遍历链表

【推荐看使用sourceInsight查看代码】

 

三、深入分析list.h

1offsetof【在已知某一个成员变量的名字和结构体类型的情况下,计算该成员相对于结构体的起始地址的偏移量】


[cpp] view plain copy

  1. #ifdef __compiler_offsetof  

  2. #define offsetof(TYPE,MEMBER)__compiler_offsetof(TYPE,MEMBER)  

  3. #else  

  4. #ifndef offsetof  

  5. #define offsetof(type, member) ((size_t) &((type*)0)->member)  

  6. #endif  


 

2container_of【已知某一个成员变量的名字、指针和结构体类型的情况下,计算结构体的指针,也就是计算结构体的起始地址】


[cpp] view plain copy

  1. #define container_of(ptr, type, member) ({ \  

  2.   const typeof(((type *)0)->member ) *__mptr = (ptr); \  

  3.   (type *)((char *)__mptr - offsetof(type,member) );})  


 

3LIST_HEAD_INIT【初始化一个结点名字为name的双向循环链表的头结点】


[cpp] view plain copy

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


 

4LIST_HEAD【初始化一个结点名字为name的双向循环链表的头结点】


[cpp] view plain copy

  1. #define LIST_HEAD(name) \  

  2.   struct list_head name = LIST_HEAD_INIT(name)  


 

5INIT_LIST_HEAD【初始化链表节点,将next和prev指针都指向其自身,我们就构造了一个空的双循环链表。】


[cpp] view plain copy

  1. static __INLINE__ void INIT_LIST_HEAD(struct list_head *list)  

  2. {  

  3.   list->next= list;  

  4.   list->prev= list;  

  5. }  


 

6list_add【在头结点后加一个新结点】


[cpp] view plain copy

  1. #ifndef CONFIG_DEBUG_LIST  

  2. static __INLINE__ void __list_add(struct list_head *new,  

  3.                                   struct list_head *prev,  

  4.                                   struct list_head *next)  

  5. {  

  6.   next->prev= new;  

  7.   new->next =next;  

  8.   new->prev =prev;  

  9.   prev->next= new;  

  10. }  

  11. #else  

  12. extern void __list_add(struct list_head *new,  

  13.                        struct list_head *prev,  

  14.                        struct list_head *next);  

  15. #endif  

  16.    

  17. static __INLINE__ void list_add(struct list_head *new,struct list_head *head)  

  18. {  

  19.  __list_add(new, head, head->next);  

  20. }  


 

7list_add_tail【添加结点new到链表尾】


[cpp] view plain copy

  1. static __INLINE__ void list_add_tail(struct list_head *newstruct list_head *head)  

  2. {  

  3.  __list_add(new, head->prev, head);  

  4. // 在head->prev和head之间加入new,即在链表尾加入new结点  


 

8list_del【list_del将会将该节点与外界的“联系”切断,然后就可以使用free释放了(如果是内核态就用kfree或vfree)】


[cpp] view plain copy

  1. #define LIST_POISON1 0  

  2. #define LIST_POISON2 0  

  3.    

  4. static __INLINE__ void __list_del(struct list_head *prev, struct list_head * next)  

  5. {  

  6.   next->prev= prev;  

  7.   prev->next= next;  

  8. }  

  9.    

  10. #ifndef CONFIG_DEBUG_LIST  

  11. static __INLINE__ void list_del(struct list_head *entry)  

  12. {  

  13.  __list_del(entry->prev, entry->next);  

  14.   entry->next= LIST_POISON1;  

  15.   entry->prev= LIST_POISON2;  

  16. }  

  17. #else  

  18. extern void list_del(struct list_head *entry);  

  19. #endif  


 

9list_replace【用结点new替换结点old


[cpp] view plain copy

  1. static __INLINE__ void list_replace(struct list_head *old,  

  2.                                     struct list_head *new)  

  3. {  

  4.   new->next =old->next;  

  5.  new->next->prev = new;  

  6.   new->prev =old->prev;  

  7.  new->prev->next = new;  

  8. }  


 

10 list_replace_init【用结点new替换结点old,并初始化old


[cpp] view plain copy

  1. static __INLINE__ void list_replace_init(struct list_head *old,  

  2.     struct list_head *new)  

  3. {  

  4.  list_replace(old, new);  

  5.  INIT_LIST_HEAD(old);  

  6. }  


 

11list_del_init【删除结点entry,并初始化entry


[cpp] view plain copy

  1. static __INLINE__ void list_del_init(struct list_head*entry)  

  2. {  

  3.  __list_del(entry->prev, entry->next);  

  4.  INIT_LIST_HEAD(entry);  

  5. }  


 

12list_move【先将list节点从原链表中删除,然后将其添加到head链表的表头】


[cpp] view plain copy

  1. static __INLINE__ void list_move(struct list_head *list, struct list_head *head)  

  2. {  

  3.  __list_del(list->prev, list->next);  

  4.   list_add(list,head);  

  5. }  


 

13list_move_tail【先将list节点从原链表中删除,然后将其添加到head链表的表尾】


[cpp] view plain copy

  1. static __INLINE__ void list_move_tail(struct list_head *list,  

  2.                                       struct list_head *head)  

  3. {  

  4.  __list_del(list->prev, list->next);  

  5.  list_add_tail(list, head);  

  6. }  


 

14list_is_last【测试list节点是否为head链表的表尾节点。是返回1,否则返回0


[cpp] view plain copy

  1. static __INLINE__ int list_is_last(const struct list_head *list,  

  2.                                    const struct list_head *head)  

  3. {  

  4.   return list->next == head;  

  5. }  


 

15list_empty【判断head链表是否为空链表,是返回1,否则返回为0


[cpp] view plain copy

  1. static __INLINE__ int list_empty(const struct list_head *head)  

  2. {  

  3.   return head->next == head;  

  4. }  




16list_empty_careful【判断节点head的前驱和后驱是否都指向head。是返回1,否则返回0


[cpp] view plain copy

  1. static __INLINE__ int list_empty_careful(const structlist_head *head)  

  2. {  

  3.   struct list_head *next = head->next;  

  4.   return (next== head) && (next == head->prev);  

  5. }  



17list_rotate_left【函数每次将头结点后的一个结点放到head链表的末尾,直到head结点后没有其他结点】


[cpp] view plain copy

  1. static __INLINE__ void list_rotate_left(struct list_head *head)  

  2. {  

  3.   struct list_head *first;  

  4.    

  5.   if(!list_empty(head))  

  6.   {  

  7.     first =head->next;  

  8.    list_move_tail(first, head);  

  9.   }  

  10. }  


 

18list_is_singular【判断head链表是否为单节点链表。是返回1,否为0


[cpp] view plain copy

  1. static __INLINE__ int list_is_singular(const struct list_head *head)  

  2. {  

  3.   return !list_empty(head) && (head->next == head->prev);  

  4. }  


 

19__list_cut_position【这个函数是将head链表的头结点至entry节点之间的节点连在list节点后面,即组成以list节点为头结点的新链表】


[cpp] view plain copy

  1. static __INLINE__ void __list_cut_position(struct list_head *list,  

  2.     struct list_head *head, struct list_head *entry)  

  3. {  

  4.   struct list_head *new_first = entry->next;  

  5.   list->next= head->next;  

  6.  list->next->prev = list;  

  7.   list->prev= entry;  

  8.   entry->next= list;  

  9.   head->next= new_first;  

  10.  new_first->prev = head;  

  11. }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  



20list_cut_position【与__list_cut_position功能相似,不过要先判断链表head是否为空链表,再判断是否为了单链表而且节点不是entry的情况,如果head==entry,直接初始化list


[cpp] view plain copy

  1. static __INLINE__ void list_cut_position(struct list_head *list,  

  2.     struct list_head *head, struct list_head *entry)  

  3. {  

  4.   if(list_empty(head))  

  5.   {  

  6.     return;  

  7.   }  

  8.   if(list_is_singular(head) &&  

  9.      (head->next != entry && head != entry))  

  10.   {  

  11.     return;  

  12.   }  

  13.   if (entry ==head)  

  14.   {  

  15.    INIT_LIST_HEAD(list);  

  16.   }  

  17.   else  

  18.   {  

  19.    __list_cut_position(list, head, entry);  

  20.   }  

  21. }  


 

21__list_splice【将list链表的全部节点(头节点list除外)插入在prevnext节点之间】


[cpp] view plain copy

  1. static __INLINE__ void __list_splice(const struct list_head *list,  

  2.                                      struct list_head *prev,  

  3.                                      struct list_head *next)  

  4. {  

  5.   struct list_head *first = list->next;  

  6.   struct list_head *last = list->prev;  

  7.    

  8.   first->prev= prev;  

  9.   prev->next= first;  

  10.    

  11.   last->next= next;  

  12.   next->prev= last;  

  13. }  


 

22list_splice_tail【在list是非空链表的情况下,将其插在head链表的尾部,即head节点的前面】


[cpp] view plain copy

  1. static __INLINE__ void list_splice_tail(struct list_head *list,  

  2.                                         struct list_head *head)  

  3. {  

  4.   if(!list_empty(list))  

  5.   {  

  6.    __list_splice(list, head->prev, head);  

  7.   }  

  8. }  


 

23list_splice_init【在list是非空链表的情况下,将其插在head链表的尾部,即head节点的前面。然后对list节点进行初始化,排除不安全因素】


[cpp] view plain copy

  1. static __INLINE__ void list_splice_init(struct list_head *list,  

  2.                                         struct list_head *head)  

  3. {  

  4.   if(!list_empty(list))  

  5.   {  

  6.    __list_splice(list, head, head->next);  

  7.    INIT_LIST_HEAD(list);  

  8.   }  

  9. }  


 

24list_splice_tail_init【在list是非空链表的情况下,将其插在head链表的尾部,即head节点的前面。然后对list节点进行初始化,排除不安全因素】


[cpp] view plain copy

  1. static __INLINE__ void list_splice_tail_init(struct list_head *list, struct list_head *head)  

  2. {  

  3.   if(!list_empty(list))  

  4.   {  

  5.    __list_splice(list, head->prev, head);  

  6.    INIT_LIST_HEAD(list);  

  7.   }  

  8. }  


 

25list_entry【获取type类型结构体的起始指针】


[cpp] view plain copy

  1. #define list_entry(ptr, type, member) \  

  2.  container_of(ptr, type, member)  


 

26list_first_entry【已知type类型的结构体中member成员的指针后,求得它所在的链表的下一个指针所指的member所在的type类型的结构体的起始地址】


[cpp] view plain copy

  1. #define list_first_entry(ptr, type, member) \  

  2.  list_entry((ptr)->next, type, member)  


 

27list_for_each【从head节点开始(不包括head节点)遍历它的每一个节点】


[cpp] view plain copy

  1. #define list_for_each(pos, head) \  

  2.   for (pos =(head)->next; prefetch(pos->next), pos != (head); \  

  3.           pos =pos->next)  


 

28list_for_each_prev【它也是从head节点开始(不包括head节点)向前遍历每一个节点!即从链表的尾部开始遍历】


[cpp] view plain copy

  1. #define list_for_each_prev(pos, head) \  

  2.   for (pos =(head)->prev; prefetch(pos->prev), pos != (head); \  

  3.           pos =pos->prev)  


 

29list_for_each_safe【从head节点开始(不包括head节点!)遍历它的每一个节点!它用n先将下一个要遍历的节点保存起来,防止删除本节点后,无法找到下一个节点,而出现错误】


[cpp] view plain copy

  1. #define list_for_each_safe(pos, n, head) \  

  2.   for (pos =(head)->next, n = pos->next; pos != (head); \  

  3.     pos = n, n =pos->next)  


 

30list_for_each_prev_safe【它也是从head节点开始(不包括head节点)向前遍历每一个节点!即从链表的尾部开始遍历】


[cpp] view plain copy

  1. #define list_for_each_prev_safe(pos, n, head) \  

  2.   for (pos =(head)->prev, n = pos->prev; \  

  3.       prefetch(pos->prev), pos != (head); \  

  4.        pos = n,n = pos->prev)  


 

31list_for_each_entry【已知指向某个结构体的指针pos,以及指向它中member成员的指针head,从下一个结构体开始向后遍历这个结构体链】


[cpp] view plain copy

  1. #define list_for_each_entry(pos, head, member)        \  

  2.   for (pos =list_entry((head)->next, typeof(*pos), member);  \  

  3.       prefetch(pos->member.next), &pos->member != (head);  \  

  4.        pos = list_entry(pos->member.next,typeof(*pos), member))  


 

32list_for_each_entry_reverse【已知指向某个结构体的指针pos,以及指向它中member成员的指针head,从下一个结构体开始向前遍历这个结构体链】


[cpp] view plain copy

  1. #define list_for_each_entry_reverse(pos, head,member)      \  

  2.   for (pos =list_entry((head)->prev, typeof(*pos), member);  \  

  3.       prefetch(pos->member.prev), &pos->member != (head);  \  

  4.        pos =list_entry(pos->member.prev, typeof(*pos), member))  


 

33list_prepare_entry【判断pos这个指针是否为空,为空的话给它赋值list_entry(head, typeof(*pos), member)这条语句求出来的结构体的地址】


[cpp] view plain copy

  1. #define list_prepare_entry(pos, head, member) \  

  2.   ((pos) ? :list_entry(head, typeof(*pos), member))  


 

34list_for_each_entry_continue【已知指向某个结构体的指针pos,以及指向它中的member成员的head指针,从它的下一个结构体开始向后遍历这个链表】


[cpp] view plain copy

  1. #define list_for_each_entry_continue(pos, head,member)     \  

  2.   for (pos =list_entry(pos->member.next, typeof(*pos), member);  \  

  3.       prefetch(pos->member.next), &pos->member != (head);  \  

  4.        pos =list_entry(pos->member.next, typeof(*pos), member))  


 

35list_for_each_entry_continue_reverse【已知指向某个结构体的指针pos,以及指向它中的member成员的head指针,从它的前一个结构体开始向前遍历这个链表】


[cpp] view plain copy

  1. #define list_for_each_entry_continue_reverse(pos,head, member)   \  

  2.   for (pos =list_entry(pos->member.prev, typeof(*pos), member);  \  

  3.       prefetch(pos->member.prev), &pos->member != (head);  \  

  4.        pos =list_entry(pos->member.prev, typeof(*pos), member))  


 

36list_for_each_entry_from【从pos节点开始,向后遍历链表】


[cpp] view plain copy

  1. #define list_for_each_entry_from(pos, head,member)       \  

  2.   for (;prefetch(pos->member.next), &pos->member != (head);  \  

  3.        pos =list_entry(pos->member.next, typeof(*pos), member))  


 

37list_for_each_entry_safe【先保存下一个要遍历的节点!从head下一个节点向后遍历链表】


[cpp] view plain copy

  1. #define list_for_each_entry_safe(pos, n, head,member)      \  

  2.   for (pos =list_entry((head)->next, typeof(*pos), member),  \  

  3.     n =list_entry(pos->member.next, typeof(*pos), member); \  

  4.       &pos->member != (head);         \  

  5.        pos = n,n = list_entry(n->member.next, typeof(*n), member))  


 

38list_for_each_entry_safe_continue【先保存下一个要遍历的节点!从pos下一个节点向后遍历链表】


[cpp] view plain copy

  1. #define list_for_each_entry_safe_continue(pos, n, head,member)     \  

  2.   for (pos =list_entry(pos->member.next, typeof(*pos), member),    \  

  3.     n =list_entry(pos->member.next, typeof(*pos), member);   \  

  4.       &pos->member != (head);           \  

  5.        pos = n,n = list_entry(n->member.next, typeof(*n), member))  


 

39list_for_each_entry_safe_from【先保存下一个要遍历的节点!从pos节点向后遍历链表】


[cpp] view plain copy

  1. #define list_for_each_entry_safe_from(pos, n, head,member)       \  

  2.   for (n =list_entry(pos->member.next, typeof(*pos), member);    \  

  3.       &pos->member != (head);           \  

  4.        pos = n, n = list_entry(n->member.next,typeof(*n), member))  


 

40list_for_each_entry_safe_reverse【先保存下一个要遍历的节点!从链表尾部向前遍历链表】


[cpp] view plain copy

  1. #define list_for_each_entry_safe_reverse(pos, n, head,member)    \  

  2.   for (pos =list_entry((head)->prev, typeof(*pos), member),  \  

  3.     n =list_entry(pos->member.prev, typeof(*pos), member); \  

  4.       &pos->member != (head);         \  

  5.        pos = n,n = list_entry(n->member.prev, typeof(*n), member))  


 

41list_safe_reset_next【获取n结构体指针】


[cpp] view plain copy

  1. #define list_safe_reset_next(pos, n, member)        \  

  2.   n =list_entry(pos->member.next, typeof(*pos), member)  


 


[cpp] view plain copy

  1. // hash链表头  

  2. struct hlist_head  

  3. {  

  4.   structh list_node *first;  

  5. };  

  6.    

  7. struct hlist_node  

  8. {  

  9.   struct hlist_node *next, **pprev;  

  10. };  


1INIT_HLIST_HEAD【初始化头节点指针ptr


[cpp] view plain copy

  1. #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)  


 

2INIT_HLIST_NODE【初始化hlist节点】


[cpp] view plain copy

  1. static __INLINE__ void INIT_HLIST_NODE(struct hlist_node *h)  

  2. {  

  3.   h->next =NULL;  

  4.   h->pprev =NULL;  

  5. }  


 

3hlist_unhashed【判断h->pprev是否为空,是返回1,否返回0


[cpp] view plain copy

  1. static __INLINE__ int hlist_unhashed(const struct hlist_node *h)  

  2. {  

  3.   return !h->pprev;  

  4. }  


 

4hlist_empty【判断hlist是否为空,是返回1,否返回0


[cpp] view plain copy

  1. static __INLINE__ int hlist_empty(const struct hlist_head *h)  

  2. {  

  3.   return !h->first;  

  4. }  


 

5__hlist_del【删除结点n


[cpp] view plain copy

  1. static __INLINE__ void __hlist_del(struct hlist_node*n)  

  2. {  

  3.   struct hlist_node *next = n->next;  

  4.   struct hlist_node **pprev = n->pprev;  

  5.   *pprev = next;  

  6.   if (next)  

  7.   {  

  8.    next->pprev = pprev;  

  9.   }  

  10. }  


 

6hlist_del【删除结点n,将结点nextpprev分别指向LIST_POISON1LIST_POISON2。这样设置是为了保证不在链表中的结点项不能被访问】


[cpp] view plain copy

  1. static __INLINE__ void hlist_del(struct hlist_node *n)  

  2. {  

  3.  __hlist_del(n);  

  4.   n->next =LIST_POISON1;  

  5.   n->pprev =LIST_POISON2;  

  6. }  


 

7hlist_del_init【先判断结点是否为空,不为空删除,再初始化节点】


[cpp] view plain copy

  1. static __INLINE__ void hlist_del_init(struct hlist_node *n)  

  2. {  

  3.   if(!hlist_unhashed(n))  

  4.   {  

  5.    __hlist_del(n);  

  6.    INIT_HLIST_NODE(n);  

  7.   }  

  8. }  


 

8hlist_add_head【增加结点nh表头】


[cpp] view plain copy

  1. static __INLINE__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h)  

  2. {  

  3.   struct hlist_node *first = h->first;  

  4.   n->next =first;  

  5.   if (first)  

  6.   {  

  7.    first->pprev = &n->next;  

  8.   }  

  9.   h->first =n;  

  10.   n->pprev =&h->first;  

  11. }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  



9hlist_add_before【增加结点n到结点next之前】


[cpp] view plain copy

  1. /* next must be != NULL */  

  2. static __INLINE__ void hlist_add_before(struct hlist_node *n,  

  3.                                         struct hlist_node *next)  

  4. {  

  5.   n->pprev =next->pprev;  

  6.   n->next = next;  

  7.   next->pprev= &n->next;  

  8.   *(n->pprev)= n;  

  9. }  


 

10hlist_add_after【增加结点n到结点next之后】


[cpp] view plain copy

  1. static __INLINE__ void hlist_add_after(struct hlist_node *n,  

  2.                                        struct hlist_node *next)  

  3. {  

  4.   next->next= n->next;  

  5.   n->next =next;  

  6.   next->pprev= &n->next;  

  7.    

  8.  if(next->next)  

  9.   {  

  10.    next->next->pprev  =&next->next;  

  11.   }  

  12. }  


 

11hlist_move_list【头结点new接管头结点old的所有节点,并初始化old


[cpp] view plain copy

  1. static __INLINE__ void hlist_move_list(struct hlist_head *old,  

  2.                                        struct hlist_head *new)  

  3. {  

  4.   new->first= old->first;  

  5.   if(new->first)  

  6.   {  

  7.    new->first->pprev = &new->first;  

  8.   }  

  9.   old->first= NULL;  

  10. }  


 

12hlist_entry【已知某一个成员变量的名字、指针和结构体类型的情况下,计算结构体的指针,也就是计算结构体的起始地址】


[cpp] view plain copy

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



13hlist_for_each【遍历hlist链表】


[cpp] view plain copy

  1. #define hlist_for_each(pos, head) \  

  2.   for (pos =(head)->first; pos ; \  

  3.        pos =pos->next)  


 

14 hlist_for_each_safe【遍历hlist链表,一般在删除结点使用】


[cpp] view plain copy

  1. #define hlist_for_each_safe(pos, n, head) \  

  2.   for (pos =(head)->first; pos && ({ n = pos->next; 1; }); \  

  3.        pos = n)  


 

15hlist_for_each_entry【遍历找typeof(*tpos)的结构体类型入口地址】


[cpp] view plain copy

  1. #define hlist_for_each_entry(tpos, pos, head,member)      \  

  2.   for (pos =(head)->first;          \  

  3.        pos&& ({ prefetch(pos->next); 1;}) &&      \  

  4.     ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \  

  5.        pos =pos->next)  


 

16hlist_for_each_entry_continue【从结点pos下一个遍历找typeof(*tpos)的结构体类型入口地址】


[cpp] view plain copy

  1. #define hlist_for_each_entry_continue(tpos, pos,member)     \  

  2.   for (pos =(pos)->next;            \  

  3.        pos&& ({ prefetch(pos->next); 1;}) &&      \  

  4.     ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \  

  5.        pos =pos->next)  


 

17hlist_for_each_entry_from【从节点pos开始遍历找typeof(*tpos)的结构体类型入口地址】


[cpp] view plain copy

  1. #define hlist_for_each_entry_from(tpos, pos,member)       \  

  2.   for (; pos&& ({ prefetch(pos->next); 1;}) &&      \  

  3.     ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \  

  4.        pos =pos->next)  


 

18hlist_for_each_entry_safe【从头节点head开始遍历找typeof(*tpos)的结构体类型入口地址】


[cpp] view plain copy

  1. #define hlist_for_each_entry_safe(tpos, pos, n, head,member)      \  

  2.   for (pos =(head)->first;          \  

  3.        pos&& ({ n = pos->next; 1; }) &&         \  

  4.     ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \  

  5.        pos = n)  





注:本文转载自http://blog.csdn.net/wqx521 ,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除。
上一篇 下一篇

分享