RT-Thread源码分析2:单链表

文章目录

    • 前情提要
    • RT-Thread单链表构造
    • 单链表节点数据结构
    • 双链表处理函数
      • 1. 初始化链表对象
      • 2. 初始化一个单链表
      • 3. 在单向链表l的尾部追加一个节点
      • 4. 向单向链表节点l后插入一个节点n
      • 5. 获取单向链表的长度
      • 6. 从单向链表l中移除一个节点n
      • 7. 获取单向链表的第一个节点
      • 8. 获取单向链表的最后一个节点
      • 9. 获取单向链表节点n的下一个节点
      • 10. 判断单向链表是否为空
    • 关于作者

前情提要

源码文件:RT-Thread Nano V3.1.3\include\rtservice.h (源文件修改日期:2017-11-15)
RT-Thread官网:https://www.rt-thread.org/

RT-Thread内核采用面向对象的设计思想进行设计,系统级的基础设施都是一种内核对象,例如线程,信号量,互斥量,定时器等。

对象容器中包含了每类内核对象的信息,包括对象类型,大小等。

对象容器给每类内核对象分配了一个链表,所有的内核对象都被链接到该链表上。

如图 RT-Thread 的内核对象容器及链表如下图所示:
RT-Thread源码分析2:单链表_第1张图片
由此可见,学习内核源码前,需要了解链表的构造及实现函数。

RT-Thread Nano V3.1.3\include\rtservice.h中包含单链表和双链表,本文学习单链表。

需要提醒的是:单链表在RT-Thread Nano内核中并未用到,内核主要使用双链表的数据结构。

关于双链表内容,请参考作者另一篇文章:RT-Thread源码分析1:双链表


RT-Thread单链表构造

RT-Thread单链表的每个节点仅有一个指针类型成员nextnext指向下一个链表节点。

链表构造示意图如下:
RT-Thread源码分析2:单链表_第2张图片


单链表节点数据结构

/**
 * Single List structure
 */
struct rt_slist_node
{
    struct rt_slist_node *next;                         /**< point to next node. */
};
typedef struct rt_slist_node rt_slist_t;                /**< Type for single list. */

双链表处理函数


函数定义中用到的宏定义说明
rt_inline,定义如下,static 关键字的作用是令函数只能在当前的文件中使用;inline 表示内联,用 static 修饰后在调用函数时会建议编译器进行内联展开。

#define  rt_inline  static __inline 

1. 初始化链表对象

#define RT_SLIST_OBJECT_INIT(object) { RT_NULL }

2. 初始化一个单链表

/**
 * @brief initialize a single list
 *
 * @param l the single list to be initialized
 */
rt_inline void rt_slist_init(rt_slist_t *l)
{
    l->next = RT_NULL;
}

l 将要被初始化的单向链表
在这里插入图片描述

3. 在单向链表l的尾部追加一个节点

rt_inline void rt_slist_append(rt_slist_t *l, rt_slist_t *n)
{
    struct rt_slist_node *node;

    node = l;
    while (node->next) node = node->next;

    /* append the node to the tail */
    node->next = n;
    n->next = RT_NULL;
}

l 被操作的链表
n 将要被追加的节点
RT-Thread源码分析2:单链表_第3张图片

4. 向单向链表节点l后插入一个节点n

rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n)
{
    n->next = l->next;
    l->next = n;
}

l 被插入的链表节点
n 将要被插入的节点
RT-Thread源码分析2:单链表_第4张图片

5. 获取单向链表的长度

rt_inline unsigned int rt_slist_len(const rt_slist_t *l)
{
    unsigned int len = 0;
    const rt_slist_t *list = l->next;
    while (list != RT_NULL)
    {
        list = list->next;
        len ++;
    }

    return len;
}

l 单向链表的链表头

6. 从单向链表l中移除一个节点n

rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n)
{
    /* remove slist head */
    struct rt_slist_node *node = l;
    while (node->next && node->next != n) node = node->next;
    /* 当前节点指向NULL时,或当前节点指向n时,执行以下代码 */
    /* remove node */
    if (node->next != (rt_slist_t *)0) node->next = node->next->next;

    return l;
}

l 单向链表的链表头
n 将要被移除的节点,指定的任意一个节点

7. 获取单向链表的第一个节点

rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l)
{
    return l->next;
}

l 单向链表的链表头

8. 获取单向链表的最后一个节点

rt_inline rt_slist_t *rt_slist_tail(rt_slist_t *l)
{
    while (l->next) l = l->next;

    return l;
}

l 单向链表的链表头

9. 获取单向链表节点n的下一个节点

rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n)
{
    return n->next;
}

n 单向链表的节点

10. 判断单向链表是否为空

rt_inline int rt_slist_isempty(rt_slist_t *l)
{
    return l->next == RT_NULL;
}

l 单向链表的链表头


本文完~

关于作者

微信公众号:萤火虫的电子笔记

分享电子产品开发软、硬件方面知识,51单片机、STM32、ARM、AltiumDesigner PCB设计、开发平台、软件工具等知识分享。

欢迎转发,请注明出处及作者。关注微信公众号,获取最新文章动态。
在这里插入图片描述

你可能感兴趣的:(嵌入式:RTOS,RT-Thread,链表,单链表)