文章目录
前情提要
源码文件: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 Nano V3.1.3\include\rtservice.h中包含单链表和双链表,本文学习单链表。
需要提醒的是:单链表在RT-Thread Nano内核中并未用到
,内核主要使用双链表的数据结构。
关于双链表内容,请参考作者另一篇文章:RT-Thread源码分析1:双链表
RT-Thread单链表构造
RT-Thread单链表的每个节点仅有一个指针类型成员next
,next
指向下一个链表节点。
链表构造示意图如下:
单链表节点数据结构
/**
* 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
将要被追加的节点
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
将要被插入的节点
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设计、开发平台、软件工具等知识分享。
欢迎转发,请注明出处及作者。关注微信公众号,获取最新文章动态。