RT_Thread内核源码分析(二)——链表和对象管理

       

目录

1、链表

1.1 双向链表

1.1.1 链表结构

1.1.2 链表操作

1.1.3 链表遍历

1.2 单向链表

1.2.1 链表结构 

1.2.2 链表操作

1.2.3 链表遍历

2、对象

2.1 内核对象结构

2.2 内核对象分类

2.3 内核对象容器

2.4 内核对象继承 

2.5 内核对象操作

2.6 内核对象钩子


         实时操作系统基本上都是通过一些链表进行线程、信号、队列的管理,RT_Thread也不例外,本章主要讲解RT_Thread的链表结构和对象管理。

本章基于RT_Thread Nano V3.1.5版本分析

      

1、链表

          RT_Thread使用的链表非常简单,链表节点只有节点指针,各节点在实例结构体中定义,可以通过头节点定位链表,可以通过节点在结构体中的偏移定位实例结构体。

1.1 双向链表

1.1.1 链表结构

        双向链表结构声明如下

struct rt_list_node
{
    struct rt_list_node *next;                          /**< 指向下一个节点. */
    struct rt_list_node *prev;                          /**< 指向上一个节点. */
};

        双向链表通过一个头节点对整个链表管理,如下所示,NODE1为头节点,用于定位链表,NODE2~NODEn为被链表管理的节点。

        双向链表主要用于对象、线程、定时器等实例管理,这些管理均需要提前设置头节点,如下所示,为系统内核定义的双链表头节点,还有一些头节点在结构体中定义,此处不再详述。

/********线程全局变量********/
extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX]; // 就绪线程链表数组
extern rt_list_t rt_thread_defunct;                                // 失效线程链表
/* 软件定时器链表 soft timer list */
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
/* 硬件定时器 hard timer list */
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];


1.1.2 链表操作

        链表操作采用内联函数和宏定义的方式,可以免去操作时的环境存储与恢复,提高运行效率。操作接口主要有初始化、插入节点(表头或表尾)、删除节点。

初始化

/*节点初始化(节点指针均指向自己)*/
#define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }

/*链表头节点初始化(节点指针均指向自己)*/
rt_inline void rt_list_init(rt_list_t *l)
{
    l->next = l->prev = l;
}

插入节点至表头

/*节点n插入到链表l的头部*/
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
    l->next->prev = n;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

  NODE1为头节点,用于定位链表,NODE2~NODEn为链表管理的节点,NewNode为新插入的节点。

   插入节点至表尾

/*节点n插入到链表l的尾部*/
rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
    l->prev->next = n;
    n->prev = l->prev;

    l->prev = n;
    n->next = l;
}

         NODE1为头节点,用于定位链表,NODE2~NODEn为链表管理的节点,NewNode为新插入的节点。

删除节点

/*链表移除节点n*/ 
rt_inline void rt_list_remove(rt_list_t *n)
{
    n->next->prev = n->prev;
    n->prev->next = n->next;
    n->next = n->prev = n;
}

         NODE1为头节点,用于定位链表,DeleteNode、NODE2~NODEn为链表管理的节点,该图为删除节点DeleteNode。

1.1.3 链表遍历

        链表遍历接口采用内联函数和宏定义的方式,可以免去操作时的环境存储与恢复,提高运行效率。

        链表节点多数存储在各类对象的结构体中,当遍历到一个节点时,可通过节点在结构体中的偏移获取结构体指针。所以链表本质上是对对象(结构体)的管理,因此,链表遍历不仅可以遍历节点,还可以遍历对象(结构体)。

/****判断链表条目数为空****/ 
rt_inline int rt_list_isempty(const rt_list_t *l)
{
    return l->next == l;
}
/****获取链表长度****/
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 = p->next;
        len ++;
    }
    return len;
}
/****遍历链表节点(pos为遍历出的节点,head为头节点)*/
#define rt_list_for_each(pos, head)       \  
for(pos=(head)->next;pos!= (head);pos = pos->next)

/*****遍历链表节点(安全模式,防止误删除,pos为遍历出的节点,n指向pos下个节点,head为头节点) */
#define rt_list_for_each_safe(pos, n, head) \
for(pos=(head)->next,n=pos->next; pos!=(head); pos=n, n=pos->next)

/****定位对象(根据节点定位)***/
#define rt_container_of(ptr,type,member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/****获取元素*/
#define rt_list_entry(node, type, member) rt_container_of(node, type, member)

/*****遍历对象*/
#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)

/******遍历对象(安全模式,防止误删除)  */
#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); \
         &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿来不是梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值