RT-Thread 内核架构图
从上图可以看到,RT-Thread实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等等,内核最小的资源占用情况是 3KB ROM,1.2KB RAM
启动流程分析一般执行顺序是:系统先从启动文件开始运行,然后进入 RT-Thread 的启动 rtthread_startup() ,最后进入用户入口 main(),如下图所示:
rtthread_startup() 函数的代码如下所示:
这部分启动代码,大致可以分为四个部分:
(1)初始化与系统相关的硬件;
(2)初始化系统内核对象,例如定时器、调度器、信号;
(3)创建 main 线程,在 main 线程中对各类模块依次进行初始化;
(4)初始化定时器线程、空闲线程,并启动调度器。
自动初始化机制自动初始化机制是指初始化函数不需要被显式调用,只需要在函数定义处通过宏定义的方式进行申明,就会在系统启动过程中被执行。
用来实现自动初始化功能的宏接口定义详细描述如下表所示:
1 | INIT_BOARD_EXPORT(fn) | 非常早期的初始化,此时调度器还未启动 |
2 | INIT_PREV_EXPORT(fn) | 主要是用于纯软件的初始化、没有太多依赖的函数 |
3 | INIT_DEVICE_EXPORT(fn) | 外设驱动初始化相关,比如网卡设备 |
4 | INIT_COMPONENT_EXPORT(fn) | 组件初始化,比如文件系统或者 LWIP |
5 | INIT_ENV_EXPORT(fn) | 系统环境初始化,比如挂载文件系统 |
6 | INIT_APP_EXPORT(fn) | 应用初始化,比如 GUI 应用 |
线程管理
系统中总共存在两类线程,分别是系统线程和用户线程。
线程管理是通过结构体struct rt_thread ,包含了优先级、线程名称、线程状态等信息
线程具有独立的线程栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。
线程状态分:初始,就绪,运行,挂起,关闭
系统线程:空闲线程和主线程
涉及到的主要函数如下
时钟节拍和定时器
线程的延时、线程的时间片轮转调度以及定时器超时等离不开时钟节拍,是系统运行的心跳
定时器分HARD_TIMER 模式与 SOFT_TIMER 模式,机制分单次触发和周期触发两种
定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序(Skip List算法)的方式插入到 rt_timer_list 链表中。
设计到主要函数
信号量,互斥量和事件集三种方式
信号量:二值,多值,优先级反转,生产者和消费者问题
互斥量:优先级继承算法解决优先级反转的问题,其他和二值信号量类似
事件集:一对多,多对多的同步
涉及到函数实现
线程通信
邮箱,消息队列,信号
邮箱:开销比较低,效率较高。每封邮件容纳固定四字节内容,一般用于传递数据指针
消息队列:邮箱的扩展,用于线程间的消息交换、使用串口接收不定长数据等。先进先出。
信号:软中断,用来通知线程发生了异步事件,用做线程之间的异常通知、应急处理
涉及到的函数实现
内存管理
总体上可分为两类:内存堆管理与内存池管理,而内存堆管理又根据具体内存设备划分为三种情况:
第一种是针对小内存块的分配管理(小内存管理算法,一般小于2MB);
第二种是针对大内存块的分配管理(slab 管理算法);
第三种是针对多内存堆的分配情况(memheap 管理算法)
涉及到的函数实现
内存池,采用链表串联的结构,提高效率和减少碎片。
涉及到的函数实现
总结:
RT-Thread内核相关的一些机制和Free RTOS,uCos都有相似之处,也加入了一些特有的机制,比如内核的一些算法,启动流程+自动初始化机制,内存优化算法等,为用户提供了更便捷的服务,让用户更放心的专注应用的开发,简化了流程。