RTX操作系统支持三种调度方式:
u 抢占式调度
每个任务都有不同的优先级,任务会一直运行直到被高优先级任务抢占或者遇到阻塞式的API函数,比如os_dly_wait。
u 时间片调度
每个任务都有相同的优先级,任务会运行固定的时间片个数直到遇到系统阻塞式的API函数,比如os_dly_wait。
u 合作式调度
每个任务都有相同的优先级,而且时间片调度要被禁止。任务会一直的运行直到遇到阻塞式的API函数,比如os_dly_wait或者用户调用函数os_tsk_pass。
在实际的应用中,不同的任务需要不同的响应时间。例如,我们在一个应用中需要使用电机,键盘和LCD显示。电机比键盘和LCD需要更快速的响应,如果我们使用合作式调度器或者时间片调度,那么电机将无法得到及时的响应,这时抢占式调度是必须的。
如果使用了抢占式调度,最高优先级的任务一旦就绪,总能得到 CPU 的控制权。当一个运行着的任务被其它高优先级的任务抢占,当前任务的 CPU 使用权就被剥夺了,或者说被挂起了,那个高优先级的任务立刻得到了 CPU 的控制权。如果是中断服务程序使一个高优先级的任务进入就绪态,中断完成时,被中断的任务被挂起,优先级高的那个任务开始运行。
使用抢占式调度器,使得最高优先级的任务什么时候可以执行,可以得到 CPU 的控制权是可知的,同时使得任务级响应时间得以最优化。
总的来说,学习抢占式调度掌握最关键的一点是:抢占式调度器会为每个任务都分配一个优先级,调度器会激活就绪任务中优先级最高的任务,并运行任务就绪列表里面优先级最高的那个任务。
10.3.2 RTX抢占式调度器的实现
如果用户在RTX的配置向导中禁止使用时间片调度,那么每个任务必须配置不同的优先级。当RTX多任务启动执行后:
u 首先执行的最高优先级的任务Task1,Task1会一直运行直到遇到系统阻塞式的API函数,比如延迟,事件标志等待,信号量等待,Task1任务会被挂起,也就是释放CPU的执行权,让低优先级的任务得到执行。
u RTX操作系统继续执行任务就绪列表中下一个最高优先级的任务Task2,Task2执行过程中有两种情况:
l Task1延迟时间到,接收到信号量消息等方面的原因,在抢占式调度器的作用下,Task2的执行会被Task1抢占。
l Task2会一直运行直到遇到系统阻塞式的API函数,比如延迟,事件标志等待,信号量等待,Task2任务会被挂起,继而执行就绪列表中下一个最高优先级的任务。
u 如果用户创建了多个任务并且采用抢占式调度器的话,基本都是按照上面两条来执行。根据抢占式调度器,当前的任务要么被高优先级任务抢占,要么通过调用阻塞式API来释放CPU使用权让低优先级任务执行,没有用户任务执行时就执行空闲任务。
下面我们通过如下的框图来说明一下抢占式调度在RTX中的运行过程,让大家有一个形象的认识。
运行条件:
u 这里仅对抢占式调度进行说明。
u 创建3个任务Task1,Task2和Task3。
u Task1的优先级为1,Task2的优先级为2,Task3的优先级为3。RTX操作系统是设置的数值越小任务优先级越低,故Task3的优先级最高,Task1的优先级最低。
u 此框图是RTX操作系统运行过程中的一部分。 运行过程描述如下:
u 此时任务Task1在运行中,运行过程中由于Task2就绪,在抢占式调度器的作用下任务Task2抢占Task1的执行。Task2进入到运行态,Task1由运行态进入到就绪态。
u 任务Task2在运行中,运行过程中由于Task3就绪,在抢占式调度器的作用下任务Task3抢占Task2的执行。Task3进入到运行态,Task2由运行态进入到就绪态。
u 任务Task3运行过程中调用了阻塞式API函数,比如os_dly_wait,任务Task3被挂起,在抢占式调度器的作用下查找到下一个要执行的最高优先级任务是Task2,任务Task2由就绪态进入到运行态。
u 任务Task2在运行中,运行过程中由于Task3再次就绪,在抢占式调度器的作用下任务Task3抢占Task2的执行。Task3进入到运行态,Task2由运行态进入到就绪态。
l Round-Robin Task switching
选择是否使能时间片调度,选上单选框表示使能时间片调度,取消单选框表示不使用时间片调度。
l Round-Robin Timeout [ticks]
范围1 – 1000。
表示时间片的大小,单位是系统时钟节拍个数。
下面我们通过如下的框图来说明一下时间片调度在RTX中的运行过程,让大家有一个形象的认识。
运行条件:
u 这里仅对时间片调度进行说明。
u 创建4个同优先级任务Task1,Task2,Task3和Task4。
u 每个任务分配的时间片大小是5个系统时钟节拍。 运行过程描述如下:
u 先运行任务Task1,运行够5个系统时钟节拍后,通过时间片调度切换到任务Task2。
u 任务Task2运行够5个系统时钟节拍后,通过时间片调度切换到任务Task3。
u 任务Task3在运行期间调用了阻塞式API函数,调用函数时,5个系统时钟节拍的时间片大小还没有用完,此时会通过时间片调度切换到下一个任务Task4。
u 任务Task4运行够5个系统时钟节拍后,通过时间片调度切换到任务Task1。
上面就是一个简单的同优先级任务通过时间片调度进行任务调度和任务切换的过程。
10.5 合作式调度器
10.5.1 合作式调度器基本概念
RTX中设计的合作式调度器比较简单,实战意义不大,用户作为了解即可,项目中没有必要采用这种调度方式的任务设计,这个也是官方的意思。原话是这么说的:For most applications, this(Round Robin Pre-emptive Scheduling) is the most useful option and you should use this scheduling schemeunless there is a strong reason to do otherwise。
对于同优先级的任务,如果用户将RTX系统配置向导中时间片调度关闭后,这些同优先级的任务就是在合作式调度器的作用下运行。其表现出来的效果就是这些同优先级的任务会依次执行,每个任务会一直执行直到遇到阻塞式API函数或者函数os_tsk_pass ()就会切换到下个任务,这就是RTX中所说的合作式调度器。
运行条件:
u 这里仅对合作式调度进行说明。
u 创建4个同优先级任务Task1,Task2,Task3和Task4。 运行过程描述如下:
u 先运行任务Task1,然后调用阻塞式API或者os_tsk_pass切换到任务Task2。
u 任务Task2运行,然后调用阻塞式API或者os_tsk_pass切换到任务Task3。
u 任务Task3运行,然后调用阻塞式API或者os_tsk_pass切换到任务Task4。
u 任务Task4运行,然后调用阻塞式API或者os_tsk_pass重新切换回任务Task1。
u 一直如此循环往复下去。
u Task Configuration
l Number of concurrent running tasks
允许创建4个任务,实际创建了如下四个任务
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
l Round-Robin Task switching
使能时间片调度
l Round-Robin Timeout [ticks]
范围1 – 1000。
设置同优先级任务的时间片是5个系统时间节拍。 RTX任务调试信息:
u Task Configuration
l Number of concurrent running tasks
允许创建4个任务,实际创建了如下四个任务
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
l Round-Robin Task switching
使能时间片调度
l Round-Robin Timeout [ticks]
范围1 – 1000。
设置同优先级任务的时间片是5个系统时间节拍。 RTX任务调试信息:
u Task Configuration
l Number of concurrent running tasks
允许创建4个任务,实际创建了如下四个任务
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
l Round-Robin Task switching
使用合作式调度必须禁止时间片调度,切记。 RTX任务调试信息:
u Task Configuration
l Number of concurrent running tasks
允许创建4个任务,实际创建了如下四个任务
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
l Round-Robin Task switching
使用合作式调度必须禁止时间片调度,切记。 RTX任务调试信息: