内核2-链表

目录

1、简介

1.1、rt_container_of宏

2、双向链表

2.1、rt_list_node结构体

2.2、接口函数

2.2.1、rt_list_init()函数

2.2.2、rt_list_insert_after()函数

2.2.3、rt_list_insert_before()函数

2.2.4、rt_list_remove()函数

2.2.5、rt_list_isempty()函数

2.2.6、rt_list_len()函数3

2.3、宏接口

2.3.1、RT_LIST_OBJECT_INIT

2.3.2、rt_list_entry

2.3.3、rt_list_for_each

2.3.4、rt_list_for_each_safe 

2.3.5、rt_list_for_each_entry

2.3.6、rt_list_for_each_entry_safe

3、单向链表

3.1、接口函数

3.1.1、rt_slist_init()函数

3.1.2、rt_slist_append()函数 

3.1.3、rt_slist_insert()函数 

3.1.4、rt_slist_len()函数 

3.1.5、rt_slist_remove()函数 

3.1.6、rt_slist_first()函数 

3.1.7、rt_slist_tail()函数 

3.1.8、rt_slist_next()函数 

3.1.9、rt_slist_isempty()函数 

3.2、宏接口

3.2.1、RT_SLIST_OBJECT_INIT

 3.2.2、rt_slist_entry

3.2.3、rt_slist_for_each

3.2.4、rt_slist_for_each_entry

3.2.5、rt_slist_first_entry

3.2.6、rt_slist_tail_entry


1、简介

RTT中链表是基础(RTT到处存在链表身影)如RTT的对象容器就是由多个对象链表组成:

1.1、rt_container_of宏

这个宏可谓是链表操作的灵魂!!! 用于获取链表节点ptr所属的结构体type,其中member是链表节点ptr在结构体type中的成员名称。使用方法如下:

1)定义一个存在链表节点的结构体。

2)将链表节点插入链表。

3)rt_list_entry()函数通过链表节点计算,获取该链表节点的结构体地址。

#define rt_container_of(ptr, type, member) \
	((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

2、双向链表

2.1、rt_list_node结构体

双向链表结构体定义。

//定义双向链表节点结构体
struct rt_list_node
{
    struct rt_list_node *next;                          /* 指向下一个节点 */
    struct rt_list_node *prev;                          /* 指向前一个节点 */
};
typedef struct rt_list_node rt_list_t;                
          

2.2、接口函数

2.2.1、rt_list_init()函数

当next节点等于prev节点且等于自身地址时,表示链表是空的。

//初始化链表
void rt_list_init(rt_list_t *l)
{
	l->next = l->prev = l; //前节点等于后节点
}

2.2.2、rt_list_insert_after()函数

在链表表后插入一个节点。

rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
    l->next->prev = n; //l的下一个节点的前一个节点等于n
    n->next = l->next; //n的下一个节点等于l的下一个节点

    l->next = n; //l的下一个节点等于n
    n->prev = l; //n的前一个节点等于l
}

2.2.3、rt_list_insert_before()函数

在链表表头前插入节点。

void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
    l->prev->next = n; //l的前一个节点的下一个节点等于n
    n->prev = l->prev; //n的前一个节点等于l的前一个节点

    l->prev = n; //l的前一个节点等于n
    n->next = l; //n的下一个节点等于l
}

2.2.4、rt_list_remove()函数

从链表移除节点。

rt_inline void rt_list_remove(rt_list_t *n)
{
	n->next->prev = n->prev; //n的下一个节点的前一个节点等于n的前一个节点
	n->prev->next = n->next; //n的前一个节点的下一个节点等于n的下一个节点

	n->next = n->prev = n; //n的下一个节点等于n的前一个节点
}

2.2.5、rt_list_isempty()函数

判断链表是否为空。

rt_inline int rt_list_isempty(const rt_list_t *l)
{
	return l->next == l; //返回链表是否为空
}

2.2.6、rt_list_len()函数

返回链表的长度。

rt_inline unsigned int rt_list_len(const rt_list_t *l)
{
	unsigned int len = 0;
	const rt_list_t *p = l;
	while (p->next != l) //p的下一个节点不等于l
	{
		p = p->next; //p指向下一个节点
		len ++; //len加1
	}

	return len; //返回长度
}

2.3、宏接口

2.3.1、RT_LIST_OBJECT_INIT

该宏用于初始化双向链表。

#define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }

2.3.2、rt_list_entry

该宏用于获取链表节点所属的结构体。

#define rt_list_entry(node, type, member) \
    rt_container_of(node, type, member)

2.3.3、rt_list_for_each

该宏用于遍历双向链表。

#define rt_list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

注:此接口是不安全的!!!因为在list_for_each循环过程中,如果链表节点pos被删除(例如另一个线程在某种情况下将pos节点从链表删除),那么循环将无法正确找到链表的下一个节点。

2.3.4、rt_list_for_each_safe 

该宏用于安全的遍历双向链表。

注:该接口是安全的,因为存在一个额外的节点n用于保存链表节点pos的下一个节点。

#define rt_list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

2.3.5、rt_list_for_each_entry

该宏用于遍历双向链表所属的结构体。

#define rt_list_for_each_entry(pos, head, member) \
    for (pos = rt_list_entry((head)->next, typeof(*pos), member); \
         &pos->member != (head); \
         pos = rt_list_entry(pos->member.next, typeof(*pos), member))

2.3.6、rt_list_for_each_entry_safe

该宏用于安全的遍历双向链表所属的结构体。

#define rt_list_for_each_entry_safe(pos, n, head, member) \
    for (pos = rt_list_entry((head)->next, typeof(*pos), member), \
         n = rt_list_entry(pos->member.next, typeof(*pos), member); \
         &pos->member != (head); \
         pos = n, n = rt_list_entry(n->member.next, typeof(*n), member))

3、单向链表

3.1、接口函数

3.1.1、rt_slist_init()函数

该接口用于单链表初始化。

void rt_slist_init(rt_slist_t *l)

3.1.2、rt_slist_append()函数 

该接口用于单链表l链表尾部添加节点n。

void rt_slist_append(rt_slist_t *l, rt_slist_t *n)

3.1.3、rt_slist_insert()函数 

该接口用于单链表节点l后添加节点n。

void rt_slist_insert(rt_slist_t *l, rt_slist_t *n)

3.1.4、rt_slist_len()函数 

该接口用于获取单链表长度。

unsigned int rt_slist_len(const rt_slist_t *l)

3.1.5、rt_slist_remove()函数 

该接口用于从单链表l链表移除节点n。

rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n)

3.1.6、rt_slist_first()函数 

该接口用于从单链表l的第一个节点。

rt_slist_t *rt_slist_first(rt_slist_t *l)

3.1.7、rt_slist_tail()函数 

该接口用于从单链表l的最后一个节点。

rt_slist_t *rt_slist_tail(rt_slist_t *l)

3.1.8、rt_slist_next()函数 

该接口用于获取节点n的下一个节点。

rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n)

3.1.9、rt_slist_isempty()函数 

该接口用于判断单链表l是否为空。

int rt_slist_isempty(rt_slist_t *l)

3.2、宏接口

3.2.1、RT_SLIST_OBJECT_INIT

该接口用于初始化单链表。

#define RT_SLIST_OBJECT_INIT(object) { RT_NULL }

 3.2.2、rt_slist_entry

该宏用于获取单链表节点所属的结构体。

#define rt_slist_entry(node, type, member) \
    rt_container_of(node, type, member)

3.2.3、rt_slist_for_each

该宏用于遍历单向链表。

#define rt_slist_for_each(pos, head) \
    for (pos = (head)->next; pos != RT_NULL; pos = pos->next)

3.2.4、rt_slist_for_each_entry

该宏用于安全的遍历单向链表。

#define rt_slist_for_each_entry(pos, head, member) \
    for (pos = rt_slist_entry((head)->next, typeof(*pos), member); \
         &pos->member != (RT_NULL); \
         pos = rt_slist_entry(pos->member.next, typeof(*pos), member))

3.2.5、rt_slist_first_entry

该宏用于获取单链表第一个节点所属的结构体。

#define rt_slist_first_entry(ptr, type, member) \
    rt_slist_entry((ptr)->next, type, member)

3.2.6、rt_slist_tail_entry

该宏用于获取单链表最后一个节点所属的结构体。

#define rt_slist_tail_entry(ptr, type, member) \
    rt_slist_entry(rt_slist_tail(ptr), type, member)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值