RT-Thread学习记录

简介

RT-Thread是一款由中国开源社区主导开发的开源嵌入式实时操作系统(遵循GPLv2+许可协议,当标识产品使用了RT-Thread时可以按照自有代码非开源的方式应用在商业产品中),它包含实时嵌入式系统相关的各个组件:实时操作系统内核,TCP/IP协议栈、文件系统、libc接口、图形引擎等。

RT-Thread实时操作系统是一个分层的操作系统,它包括了:

  • 底层移植、驱动层,这层与硬件密切相关,由Drivers和CPU移植相构成。
  • 硬实时内核,这层是RT-Thread的核心,包括了内核系统中对象的实现,例如多线程及其调度,信号量,邮箱,消息队列,内存管理,定时器等实现。
  • 组件层,这些是基于RT-Thread核心基础上的外围组件,例如文件系统,命令行shell接口,lwIP轻型TCP/IP协议栈,GUI图形引擎等。

线程调度与管理

一个典型的简单程序会设计成一个串行的系统运行:按照准确的指令步骤一次一个指令的运行。但是这种方法对于复杂一些的实时应用是不可行的,因为它们通常需要在固定的时间内“同时”处理多个输入输出,实时软件应用程序应该设计成一个并行的系统。

并行设计需要开发人员把一个应用分解成一个个小的,可调度的,序列化的程序单元。当合理的划分任务,正确的并行执行时,这种设计能够让系统满足实时系统的性能及时间的要求。

1 实时系统的需求

系统的实时性指的是在固定的时间内正确地对外部事件做出响应。这个“时间内”(deadline),系统内部会做一些处理,例如输入数据的分析计算,加工处理等。而在这段时间之外,系统可能会空闲下来,做一些空余的事。

例如一个手机终端,当一个电话拨入的时候,系统应当及时发出振铃、声音提示以通知主人有来电,询问是否进行接听。而在非电话拨入的时候,人们可以用它进行一些其它工作,例如听音乐,玩游戏等。

实时系统是一种需求倾向性的系统,对于实时的事件需要在第一时间内做出回应,而对非实时任务则可以在实时事件到达时为之让路——被抢占。所以实时系统也可以看成是一个等级系统,不同重要性的任务具有不同的优先等级:重要的事件能够优先被响应执行,非重要的事件可以适当往后推迟。

在RT-Thread实时操作系统中,任务采用了线程来实现,线程是RT-Thread中最基本的调度单位,它描述了一个任务执行的上下文关系,也描述了这个任务所处的优先等级。重要的任务能拥有相对较高的优先级,非重要的任务优先级可以放低,并且可以类似Linux一样具备分时的效果。

2 线程调度器

RT-Thread中提供的线程调度器是基于优先级的全抢占式调度:在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自身。系统总共支持256个优先级(0 ~ 255,数值越小的优先级越高,0为最高优先级,255分配给空闲线程使用,一般用户不使用。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8个或32个优先级的系统配置)。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。

在RT-Thread调度器的实现中,包含了一个共256个优先级队列的数组(如果系统最大支持32个优先级,那么这里将是一个包含了32个优先级队列的数组),每个数组元素中放置相同优先级链表的表头。这些相同优先级的列表形成一个双向环形链表,最低优先级线程链表一般只包含一个idle线程。

线程就绪优先级队列

在优先级队列1#和2#中,可以看到三个线程:线程A、线程B和线程C。由于线程A、B的优先级比线程C的高,所以此时线程C得不到运行,必须要等待优先级队列1#的中所有线程(因为阻塞)都让出处理器后才能得到执行。

一个操作系统如果只是具备了高优先级任务能够“立即”获得处理器并得到执行的特点,那么它仍然不算是实时操作系统。因为这个查找最高优先级线程的过程决定了调度时间是否具有确定性,例如一个包含n个就绪任务的系统中,如果仅仅从头找到尾,那么这个时间将直接和n相关,而下一个就绪线程抉择时间的长短将会极大的影响系统的实时性。当所有就绪线程都链接在它们对应的优先级队列中时,抉择过程就将演变为在优先级数组中寻找具有最高优先级线程的非空链表。RT-Thread内核中采用了基于位图的优先级算法(时间复杂度O(1),即与就绪线程的多少无关),通过位图的定位快速的获得优先级最高的线程。

RT-Thread内核中也允许创建相同优先级的线程。相同优先级的线程采用时间片轮转方式进行调度(也就是通常说的分时调度器),时间片轮转调度仅在当前系统中无更高优先级就绪线程存在的情况下才有效。例如在 线程就绪优先级队列 图中,我们假设线程A和线程B一次最大允许运行的时间片分别是10个时钟节拍和7个时钟节拍。那么线程B将在线程A的时间片结束(10个时钟节拍)后才能运行,但如果中途线程A被挂起了,即线程A在运行的途中,因为试图去持有不可用的资源,而导致线程状态从就绪状态更改为阻塞状态,那么线程B会因为其优先级成为系统中就绪线程中最高的而马上运行。每个线程的时间片大小都可以在初始化或创建这个线程时指定。

因为RT-Thread调度器的实现是采用优先级链表的方式,所以系统中的总线程数不受限制,只和系统所能提供的内存资源相关。为了保证系统的实时性,系统尽最大可能地保证高优先级的线程得以运行。线程调度的原则是一旦任务状态发生了改变,并且当前运行的线程优先级小于优先级队列组中线程最高优先级时,立刻进行线程切换(除非当前系统处于中断处理程序中或禁止线程切换的状态)。

猜你喜欢

转载自blog.csdn.net/qq_36622903/article/details/81357886