回答

收藏

RT-Thread系统内核简介

RT-Thread RT-Thread 2420 人阅读 | 0 人回复 | 2021-04-25

内核基础
RT-Thread 内核架构图

RT-Thread 内核及底层结构
从上图可以看到,RT-Thread实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等等,内核最小的资源占用情况是 3KB ROM,1.2KB RAM

启动流程分析
一般执行顺序是:系统先从启动文件开始运行,然后进入 RT-Thread 的启动 rtthread_startup() ,最后进入用户入口 main(),如下图所示:

启动流程
rtthread_startup() 函数的代码如下所示:
  1. // components.c
  2. int rtthread_startup(void)
  3. {
  4.     rt_hw_interrupt_disable();
  5. ?
  6.     /* 板级初始化:需在该函数内部进行系统堆的初始化 */
  7.     rt_hw_board_init();
  8. ?
  9.     /* 打印 RT-Thread 版本信息 */
  10.     rt_show_version();
  11. ?
  12.     /* 定时器初始化 */
  13.     rt_system_timer_init();
  14. ?
  15.     /* 调度器初始化 */
  16.     rt_system_scheduler_init();
  17. ?
  18. #ifdef RT_USING_SIGNALS
  19.     /* 信号初始化 */
  20.     rt_system_signal_init();
  21. #endif
  22. ?
  23.     /* 由此创建一个用户 main 线程 */
  24.     rt_application_init();
  25. ?
  26.     /* 定时器线程初始化 */
  27.     rt_system_timer_thread_init();
  28. ?
  29.     /* 空闲线程初始化 */
  30.     rt_thread_idle_init();
  31. ?
  32.     /* 启动调度器 */
  33.     rt_system_scheduler_start();
  34. ?
  35.     /* 不会执行至此 */
  36.     return 0;
  37. }
复制代码
这部分启动代码,大致可以分为四个部分:

(1)初始化与系统相关的硬件;

(2)初始化系统内核对象,例如定时器、调度器、信号;

(3)创建 main 线程,在 main 线程中对各类模块依次进行初始化;

(4)初始化定时器线程、空闲线程,并启动调度器。

自动初始化机制
自动初始化机制是指初始化函数不需要被显式调用,只需要在函数定义处通过宏定义的方式进行申明,就会在系统启动过程中被执行。

用来实现自动初始化功能的宏接口定义详细描述如下表所示:
线程管理
系统中总共存在两类线程,分别是系统线程和用户线程。

线程管理是通过结构体struct rt_thread ,包含了优先级、线程名称、线程状态等信息

线程具有独立的线程栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息,进行恢复。

线程状态分:初始,就绪,运行,挂起,关闭

系统线程:空闲线程和主线程

涉及到的主要函数如下
  1. // thread.c
  2. rt_thread_t rt_thread_create(const char *name,
  3.                              void (*entry)(void *parameter),
  4.                              void       *parameter,
  5.                              rt_uint32_t stack_size,
  6.                              rt_uint8_t  priority,
  7.                              rt_uint32_t tick);
  8. rt_err_t rt_thread_init(struct rt_thread *thread,
  9.                         const char       *name,
  10.                         void (*entry)(void *parameter),
  11.                         void             *parameter,
  12.                         void             *stack_start,
  13.                         rt_uint32_t       stack_size,
  14.                         rt_uint8_t        priority,
  15.                         rt_uint32_t       tick);
  16. rt_err_t rt_thread_delete(rt_thread_t thread);
  17. rt_err_t rt_thread_startup(rt_thread_t thread);
  18. rt_err_t rt_thread_detach(rt_thread_t thread);
  19. ?
  20. rt_thread_t rt_thread_self(void);
  21. ?
  22. /**
  23. * This function will let current thread yield processor, and scheduler will
  24. * choose a highest thread to run. After yield processor, the current thread
  25. * is still in READY state.
  26. *
  27. * @return RT_EOK
  28. */
  29. rt_err_t rt_thread_yield(void);
  30. ?
  31. rt_err_t rt_thread_sleep(rt_tick_t tick);
  32. rt_err_t rt_thread_delay(rt_tick_t tick);
  33. rt_err_t rt_thread_mdelay(rt_int32_t ms);
  34. ?
  35. rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg);
  36. rt_err_t rt_thread_suspend(rt_thread_t thread);
  37. rt_err_t rt_thread_resume(rt_thread_t thread);
  38. ?
复制代码
时钟管理
时钟节拍和定时器

线程的延时、线程的时间片轮转调度以及定时器超时等离不开时钟节拍,是系统运行的心跳

定时器分HARD_TIMER 模式与 SOFT_TIMER 模式,机制分单次触发和周期触发两种

定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序(Skip List算法)的方式插入到 rt_timer_list 链表中。

设计到主要函数
  1. void rt_timer_init(rt_timer_t  timer,
  2.                    const char *name,
  3.                    void (*timeout)(void *parameter),
  4.                    void       *parameter,
  5.                    rt_tick_t   time,
  6.                    rt_uint8_t  flag);
  7. rt_err_t rt_timer_detach(rt_timer_t timer);
  8. rt_timer_t rt_timer_create(const char *name,
  9.                            void (*timeout)(void *parameter),
  10.                            void       *parameter,
  11.                            rt_tick_t   time,
  12.                            rt_uint8_t  flag);
  13. rt_err_t rt_timer_delete(rt_timer_t timer);
  14. ?
  15. rt_err_t rt_timer_start(rt_timer_t timer);
  16. rt_err_t rt_timer_stop(rt_timer_t timer);
  17. rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg);
  18. ?
复制代码

线程同步
信号量,互斥量和事件集三种方式

信号量:二值,多值,优先级反转,生产者和消费者问题

互斥量:优先级继承算法解决优先级反转的问题,其他和二值信号量类似

事件集:一对多,多对多的同步



涉及到函数实现

信号量相关接口

互斥量相关接口

事件相关接口


线程通信
邮箱,消息队列,信号

邮箱:开销比较低,效率较高。每封邮件容纳固定四字节内容,一般用于传递数据指针

消息队列:邮箱的扩展,用于线程间的消息交换、使用串口接收不定长数据等。先进先出。

信号:软中断,用来通知线程发生了异步事件,用做线程之间的异常通知、应急处理



涉及到的函数实现

邮箱相关接口

消息队列相关接口

信号相关接口


内存管理
总体上可分为两类:内存堆管理与内存池管理,而内存堆管理又根据具体内存设备划分为三种情况:

第一种是针对小内存块的分配管理(小内存管理算法,一般小于2MB);

第二种是针对大内存块的分配管理(slab 管理算法);

第三种是针对多内存堆的分配情况(memheap 管理算法)

涉及到的函数实现
  1. rt_err_t rt_memheap_init(struct rt_memheap *memheap,
  2.                          const char        *name,
  3.                          void              *start_addr,
  4.                          rt_size_t         size);
  5. rt_err_t rt_memheap_detach(struct rt_memheap *heap);
复制代码
内存池,采用链表串联的结构,提高效率和减少碎片。

涉及到的函数实现

内存池相关接口


总结:
RT-Thread内核相关的一些机制和Free RTOS,uCos都有相似之处,也加入了一些特有的机制,比如内核的一些算法,启动流程+自动初始化机制,内存优化算法等,为用户提供了更便捷的服务,让用户更放心的专注应用的开发,简化了流程。


分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条