OpenWRT篇——篇:Ubox——list.h(代码注释)

编程入门 行业动态 更新时间:2024-10-18 01:38:11

OpenWRT篇——篇:Ubox——list.h(代码<a href=https://www.elefans.com/category/jswz/34/1770285.html style=注释)"/>

OpenWRT篇——篇:Ubox——list.h(代码注释)

说明
  本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
  QQ 群 号:513683159 【相互学习】
内容来源
  

/*-* Copyright (c) 2011 Felix Fietkau <nbd@openwrt>* Copyright (c) 2010 Isilon Systems, Inc.* Copyright (c) 2010 iX Systems, Inc.* Copyright (c) 2010 Panasas, Inc.* Copyright (c) 2016 Yu Bo <yubo@yubo>* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:* 1. Redistributions of source code must retain the above copyright*    notice unmodified, this list of conditions, and the following*    disclaimer.* 2. Redistributions in binary form must reproduce the above copyright*    notice, this list of conditions and the following disclaimer in the*    documentation and/or other materials provided with the distribution.** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
#ifndef __LINUX_LIST_H__
#define __LINUX_LIST_H__
#pragma GCC diagnostic ignored "-Wcast-qual"
#include <stddef.h>
#include <stdbool.h>#define prefetch(x)/************************************************************************ 说明:*	(1)该链表属于双循环链表。*	 (2)没有数据域,因为不是在链表结构中包含数据,而是在数据结构中包含链表节点。*	 (3)没有固定的表头,任何元素开始访问都可以。*	 (4)遍历链表时仅需从某节点开始直到回到最初节点即可。*	 (5)每个独立的节点都可称为链表头。***********************************************************************//*** @brief 通过“结构体成员”的地址与“结构体”的类型推导出“结构体”的首地址** @ptr:    “结构体成员”的地址* @type:   “结构体”的类型* @member: “结构体成员”的名字*/
#ifndef container_of
#define container_of(ptr, type, member)                       \({                                                        \const typeof(((type *)NULL)->member) *__mptr = (ptr); \(type *)((char *)__mptr - offsetof(type, member));    \})
#endif
/*(1).typeof()返回传入数据的类型,如int a = 3;typeof(a) = int(2.offsetof(type, member):在类型为type的结构体中member成员,在该结构体中的偏移量type:结构体类型,member:结构体中某个成员
分析:A = ((type *) NULL)表示:type类型的指针地址为0,B = (A->member)表示:该结构体类型(地址为0)的成员memberC = typeof(B)表示:返回结构体成员member的数据类型D = const C* __mptr = (ptr)表示:__mptr的地址为ptr的成员地址(数据类型统一的成员地址)E = offsetof(type, member)表示:类型为type的结构体中member成员,member在该结构体中的偏移量F = (type *) ((char *)__mptr - E= ptr - E (忽略类型) = 成员的地址 - 成员的偏移量 = 结构体的的初始地址 = 结构体指针地址
*//* 双链表结构体 */
struct list_head
{struct list_head *next; /* 后继指针 */struct list_head *prev; /* 前驱指针 */
};/* 双链表的创建与初始化(宏定义),本质:定义并初始化某链表节点 */
#define LIST_HEAD_INIT(name) \{                        \&(name), &(name)     \}
#undef LIST_HEAD             /* 取消之前LIST_HEAD的宏定义 */
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
/*声明一个为name的链表头,next于prev指针指向自己,即:创建一个空链表。LIST_HEAD(DList)等效于struct list_head DList{&DList,&DList}等效于struct list_head DList;DList.prev = &DList;DList.next = &DList;*//*** @brief 链表初始化(内联函数)* @param list 双链表对象* @description:*      初始化某链表节点*/
static inline void
INIT_LIST_HEAD(struct list_head *list)
{list->next = list->prev = list;
}/*** @brief 判断链表为不为空** @param head 	:链表节点(通常为头节点)* @return true :该链表为空* @return false:该链表不为空** @description:*      若链表的下一个节点指向自己则表示该链表为空*/
static inline bool
list_empty(const struct list_head *head)
{return (head->next == head);
}/*** @brief 判断list节点是否为头节点(第一个有数据的节点)** @param list	:想判断的节点* @param head	:链表表头节点* @return true	:list节点是头节点* @return false:list节点是头节点** @description:*      判断head节点是不是list节点的前节点*      判断链表list节点的前一节点是不是head节点*/
static inline bool
list_is_first(const struct list_head *list,const struct list_head *head)
{return list->prev == head;
}/*** @brief   判断list节点是否为尾节点(最后一个有数据的节点)** @param list	:想判断的节点* @param head	:链表表头节点* @return true	:list节点是尾节点* @return false:list节点是尾节点* @description:*      判断head节点是不是list节点的后节点*      判断链表list节点的后一节点是不是head节点*/
static inline bool
list_is_last(const struct list_head *list,const struct list_head *head)
{return list->next == head;
}/*** @brief 删除entry节点** @param entry: 要删除的节点* @description:*      将entry节点的后继节点的prev指针指向entry节点的前一节点*      将entry节点的前驱节点的next指针只想entry节点的后一节点*/
static inline void
_list_del(struct list_head *entry)
{entry->next->prev = entry->prev;entry->prev->next = entry->next;
}/*** @brief 删除entry节点,并清空指针** @param entry: 要删除的节点*/
static inline void
list_del(struct list_head *entry)
{_list_del(entry);entry->next = entry->prev = NULL;
}/*** @brief 在prev与next链表节点中插入_new链表节点** @param _new: 新的链表节点* @param prev: 插入节点的前节点* @param next: 插入节点的后节点*/
static inline void
_list_add(struct list_head *_new, struct list_head *prev,struct list_head *next)
{next->prev = _new;_new->next = next;_new->prev = prev;prev->next = _new;
}/*** @brief 删除entry节点并初始化该节点为新链表表头** @param entry : 要删除的节点并作为新链表表头*/
static inline void
list_del_init(struct list_head *entry)
{_list_del(entry);INIT_LIST_HEAD(entry);
}/*** @brief 将old节点替换为new节点** @param old 被替换的链表节点* @param new 新的链表节点*/
static inline void
replace_node(struct list_head *old, struct list_head *new)
{old->next->prev = new;old->prev->next = new;new->prev = old->prev;new->next = old->next;
}/****** 获取含有链表的结构体的指针 ******/
#define list_entry(ptr, type, field) container_of(ptr, type, field)             /* 从链表指针ptr中获得包含该链表的结构体指针 */
#define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field) /* 从链表指针ptr的下一指针中获得包含该链表的结构体指针 */
#define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field)  /* 从链表指针ptr的上一指针中获得包含该链表的结构体指针 */
/*ptr:   表示和member同为相同类型的链表,此处ptr表示指向链表中的一个节点(list_head指针)type: 表示需要寻找的结构体类型(包含链表结构的结构体类型)field:表示type类型的结构体里面的成员(结构体中链表字段的名字,常为:list)常用解释:(ptr常为链表表头节点)(一)list_entry,表示:获取链表中ptr节点,该节点的数据了类型为type,type中包含的链表变量为list;(二)list_first_entry,ptr节点常为表头节点,表示:获取链表的第一个节点数据。(三)list_last_entry,ptr节点常为表头节点,表示:获取链表的最后一个节点数据。
*//*** @brief:  遍历表头为head的链表** @param p    :list_head指针,此处作为一个暂存地址变量(head的next指针)* @param head :常为链表表头*/
#define list_for_each(p, head) \for ((p) = (head)->next; (p) != (head); (p) = (p)->next)/*** @brief:   安全遍历表头为head的链表** @param p    :list_head指针,此处作为一个暂存地址变量(head的next指针)* @param n    :list_head指针,此处作为一个暂存地址变量(p的next指针)* @param head :常为链表表头*/
#define list_for_each_safe(p, n, head)                     \for ((p) = (head)->next, n = (p)->next; (p) != (head); \(p) = n, n = (p)->next)/************************ 遍历链表的同时获得结构体指针 ******************************//*** @brief   遍历表头为head的链表,同时获得节点结构体指针** @param p     :节点结构体的暂存地址变量* @param h     :该双链表的表头地址* @param field :节点结构体中链表字段的名字,常为:list*/
#define list_for_each_entry(p, h, field)                 \for ((p) = list_first_entry(h, typeof(*(p)), field); \&(p)->field != (h);                             \(p) = list_entry((p)->field.next, typeof(*(p)), field))/*** @brief   遍历表头为head的链表,同时释放每个被遍历到的节点** @param p     :节点结构体的暂存地址变量* @param n     :暂存p节点结构体的暂存地址变量* @param h     :该双链表的表头地址* @param field :节点结构体中链表字段的名字,常为:list*/
#define list_for_each_entry_safe(p, n, h, field)              \for ((p) = list_first_entry(h, typeof(*(p)), field),      \n = list_entry((p)->field.next, typeof(*(p)), field); \&(p)->field != (h);                                  \(p) = n, n = list_entry(n->field.next, typeof(*n), field))/*** @brief   反向遍历表头为head的链表,同时获得节点结构体指针** @param p     :节点结构体的暂存地址变量* @param h     :该双链表的表头地址* @param field :节点结构体中链表字段的名字,常为:list*/
#define list_for_each_entry_reverse(p, h, field)        \for ((p) = list_last_entry(h, typeof(*(p)), field); \&(p)->field != (h);                            \(p) = list_entry((p)->field.prev, typeof(*(p)), field))/*** @brief:  反向遍历表头为head的链表** @param p    :list_head指针,此处作为一个暂存地址变量(head的prev指针)* @param head :常为链表表头*/
#define list_for_each_prev(p, h) \for ((p) = (h)->prev; (p) != (h); (p) = (p)->prev)/*** @brief:   反向安全遍历表头为head的链表** @param p    :list_head指针,此处作为一个暂存地址变量(head的prev指针)* @param n    :list_head指针,此处作为一个暂存地址变量(p的prev指针)* @param head :常为链表表头*/
#define list_for_each_prev_safe(p, n, h) \for ((p) = (h)->prev, n = (p)->prev; \(p) != (h); (p) = n, n = (p)->prev)/*** list_for_each_entry_continue - continue iteration over list of given type* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_struct within the struct.** Continue to iterate over list of given type, continuing after* the current position.*/
#define list_for_each_entry_continue(pos, head, member) \list_for_each_entry(pos, head, member)/*** @brief 将_new节点插在head节点后面** @param _new:新节点* @param head:目标节点*/
static inline void
list_add(struct list_head *_new, struct list_head *head)
{_list_add(_new, head, head->next);
}/*** @brief 将_new节点插在head节点前面** @param _new:新节点* @param head:目标节点*/
static inline void
list_add_tail(struct list_head *_new, struct list_head *head)
{_list_add(_new, head->prev, head);
}/*** @brief 将list节点移到head节点后面*		  从链表中删除list项后将其插入head的后面* @param list:要移动的节点* @param head:目标节点*/
static inline void
list_move(struct list_head *list, struct list_head *head)
{_list_del(list);list_add(list, head);
}/*** @brief 将entry节点移到head节点前面*		  从链表中删除entry项后将其插入head的前面* @param entry:要移动的节点* @param head: 目标节点*/
static inline void
list_move_tail(struct list_head *entry, struct list_head *head)
{_list_del(entry);list_add_tail(entry, head);
}/** list: src* prev: add  list after node* next: insert list befor node*//*** @brief 将双循环链表从list节点处分割,* 		  list节点前接上next节点链表,list节点后街上prev节点链表*		  【注意】:合并好的新链表是不包含list节点,且未构成循环* @param list :要插入的两条链表的节点位置* @param prev :要插入的前一条链表节点* @param next :要插入的后一条链表节点*/
static inline void
_list_splice(const struct list_head *list, struct list_head *prev,struct list_head *next)
{struct list_head *first;struct list_head *last;/* 若list链表为空则无需合并直接退出 */if (list_empty(list))return;first = list->next; /* list节点的后一节点 */last = list->prev;  /* list节点的前一节点 */first->prev = prev; /* 后一节点的前驱指针指向prev链表 */prev->next = first; /* prev链表的后继指针指向后一节点 */last->next = next;  /* 前一节点的后继指针指向next链表 */next->prev = last;  /* next链表的前驱指针指向last链表 */
}/*** @brief 将head节点及其【后】的节点分别接在list节点的两端(拼接函数【后】)** 		  将双循环链表从list节点处分割,* 		  list节点前接上head->next节点链表,list节点后接上head节点链表*		 【注意】:合并好的新链表是不包含list节点,且未构成循环* @param list:要插入的两条链表的节点位置* @param head:想要拆接的head节点*/
static inline void
list_splice(const struct list_head *list, struct list_head *head)
{_list_splice(list, head, head->next);
}/*** @brief 将head节点及其【前】的节点分别接在list节点的两端(拼接函数【前】)** 		  将双循环链表从list节点处分割,* 		  list节点前接上headt节点链表,list节点后接上head->prev节点链表*		 【注意】:合并好的新链表是不包含list节点,且未构成循环* @param list:要插入的两条链表的节点位置* @param head:想要拆接的head节点*/
static inline void
list_splice_tail(struct list_head *list, struct list_head *head)
{_list_splice(list, head->prev, head);
}/*** @brief 拼接函数【后】并初始化该节点** @param list:要插入的两条链表的节点位置* @param head:想要拆接的head节点*/
static inline void
list_splice_init(struct list_head *list, struct list_head *head)
{_list_splice(list, head, head->next);INIT_LIST_HEAD(list);
}/*** @brief 拼接函数【前】并初始化该节点** @param list:要插入的两条链表的节点位置* @param head:想要拆接的head节点*/
static inline void
list_splice_tail_init(struct list_head *list, struct list_head *head)
{_list_splice(list, head->prev, head);INIT_LIST_HEAD(list);
}#define list_entity list_head#define list_init_head(_list) INIT_LIST_HEAD(_list)
#define list_add_head(_head, _list) list_add(_list, _head)
#define list_add_after(_after, _list) list_add(_list, _after)
#define list_add_before(_before, _list) list_add_tail(_list, _before)
#define list_remove(_list) list_del(_list)
#define list_is_empty(_list) list_empty(_list)
#define list_next_element(_element, _member) list_entry((_element)->_member.next, typeof(*(_element)), _member)#endif /* _LINUX_LIST_H_ */

更多推荐

OpenWRT篇——篇:Ubox——list.h(代码注释)

本文发布于:2024-02-26 11:13:57,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1702281.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:注释   代码   OpenWRT   Ubox   list

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!