基于STM32的mbedOS线程信号剖析
2022-02-15王浩波王宜怀刘长勇刘中华
王浩波,王宜怀,刘长勇,刘中华
(1.苏州大学 计算机科学与技术学院,江苏 苏州 215006; 2.武夷学院 数学与计算机学院,福建 武夷山 354300)
0 引 言
实时操作系统RTOS[1](real time operation system)是一种具备较高实时性及稳定性的嵌入式系统。一个复杂的嵌入式系统整体功能可以在RTOS的支持下,通过任务间通信的方式保证各个任务间能协调有序、互不冲突地同步运行。线程信号作为RTOS的同步与通信方式中最基本的一种,用来通知线程发生了异步事件,进而实现线程间消息传递。截至目前,也有少数学者在线程信号响应机制原理方面展开研究。例如,uClinux实时操作系统是通过信号屏蔽字的方式实现任务间协同管理与控制[2]。而Vxworks的任务间同步与通信是在软件信号[3]设立的基础上完成。eCOS则是利用条件变量来完成任务间的通信[4]。
但是,这些研究仅针对线程信号的调用算法或应用展开研究,而对RTOS内部的线程信号响应原理、响应时间性能或运行流程并未介绍,不足以让读者深刻理解同步与通信原理机制。为此,通过对RTOS的线程信号通信原理、响应流程以及其它关键技术要点的分析,在此基础上提出基于printf方法输出线程信号响应机制流程的剖析方法,以STM32L431芯片为例,在mbedOS测试工程中不仅给出了printf输出语句的加入位置及方法,同时也对线程信号内部响应机制流程及时间进行了系统分析[5]。结果分析表明,将线程信号内部整个响应机制流程信息通过printf方法输出显示在PC机中,不仅有助于读者从更加微观的层面来理解同步与通信原理机制,也为深入理解或设计新的RTOS提供了重要的理论研究基础。
1 线程信号响应机制原理及关键技术要点
在RTOS的同步与通信机制中,相比于通过事件字来表达多种可能的逻辑结果,线程信号是最简单的同步手段,常应用于协调任务间或中断与任务间的通信、仅表达某一具体的情况而无需传递数据的场景。
1.1 线程信号的作用及响应机制原理
线程信号作为线程间通信的重要媒介之一,用来通知线程发生了异步事件,操作系统内核也可以因为内部事件而给线程发送信号,通知线程发生了某个事件,在mbedOS中采用线程信号、eCOS中采用条件变量、uClinux中采用信号屏蔽字、Vxworks中采用软件信号的方式来实现。
若两个任务间的同步与通信是通过线程信号的方式来实现,则其中必定会有一个任务通过某种方式在等待该线程信号,同时另外一个任务则采用某种方式或函数设置具体的线程信号值,例如在mbedOS中,线程调用signal_wait函数等待一个线程信号,实际上是将所要等待的线程信号值记录在线程控制块的waitFlags变量中;在uClinux实时操作系统中,等待信号的产生由sigwait函数完成;Vxworks则是在程序执行到sig_suspend这一函数处,系统挂起当前任务并等待具体的软件信号值;而eCOS在等待条件变量前会先调用cyg_cond_wait这一函数。这个时候任务状态由就绪态切换为阻塞态,并从就绪队列移出再放到等待队列中。之后会在另一任务设置线程信号值,如mbedOS通过调用线程设置函数signal_set设置线程信号值,实际是将要设置的具体线程信号值记录在线程控制块的threadFlags变量中;uClinux向特定的任务发送信号前会先调用signal函数;Vxworks在kill函数的作用下,向特定的任务发送具体的信号值;而eCOS唤醒所有等待条件变量前,会事先调用cyg_cond_broadcast或cyg_cond_signal函数,可分别唤醒多个或一个等待该条件变量的线程。之后它们会在各自的线程信号设置处判断其中是否有等待具体信号值的任务或线程,若有则将其状态由阻塞态切换为就绪态,并从等待队列移出再放到就绪队列中。4种操作系统的线程信号调度对比过程如图1所示。
图1 4种操作系统的线程信号调度对比过程
1.2 线程信号响应机制的关键技术要点
在线程信号响应机制的过程中,会涉及到线程信号的等待、线程信号的产生、线程信号的存储、线程信号的识别、线程信号的响应以及线程信号的调度等关键技术要点。
(1)线程信号的等待:其定义请参见文献[6];
(2)线程信号的产生:即指明线程信号由谁负责设置,在什么时间以及什么位置被设置,设置的线程信号值是多少;
(3)线程信号的存储:即线程信号被设置完成后,指明线程信号值存储的时间和存储位置;
(4)线程信号的识别:线程信号被存储后,指明线程信号被识别的时间和识别对象;
(5)线程信号的响应:其定义请参见文献[6];
(6)线程信号的调度:其定义请参见文献[6]。
2 基于printf方法分析线程信号响应机制原理
若任务间的同步与通信机制是通过线程信号的方式来实现,则其内部等待和设置线程信号的过程通常是隐藏在内核程序中,通过printf措施将线程信号内部响应的中间流程信息直观地显示在PC机中并加以剖析,可以帮助读者捋清线程信号响应的整个脉络结构,加深对该同步与通信方式的理解。
2.1 printf输出可行性分析
要理解线程信号响应机制的过程,可以通过以下3种方法。第一种是直接查看源程序的方法,直接根据程序代码含义来分析整个程序的执行流程,该方法对于无操作系统程序或单一程序的分析是可行的[6]。但对RTOS而言,程序的执行是非静态且并非一次性运行完成,而是由RTOS根据调度策略(mbedOS中采用优先级抢占以及时间片轮询调度策略)对任务进行动态调度。因此,直接分析源程序这种静态的方式很难模拟出RTOS轮询调度的动态过程[7]。第二种是通过断点调试手段,即在需要调试的语句上进行断点设置,通过单步跟踪的方式逐语句分析线程信号响应流程。但在有RTOS的情况下,其内部会存在一个定时器中断,该中断会在每个时间嘀嗒到来时自动运行,若采取断点调试的措施,则无法进入到定时器中断内部进行语句分析,也就无法分析线程信号的响应机制。还有一种是printf输出方法,printf调试方法[8]作为动态分析的最原始形式之一,被广泛应用在各个领域中。例如:在CPU仿真技术中通过printf方法可以打印输出调试信息;在计算机视觉应用中通过printf调试方法将中间过程信息打印输出;还可以在程序功能分析过程中采用printf调试方法输出程序错误信息。因此,借鉴类PC机的printf调试方法,不但能够实现将线程信号响应过程的各种状态动态地输出显示在PC机中,也有助于更好地剖析线程信号响应机制的内部过程。
2.2 printf插入法分析
为更好地剖析线程信号响应机制过程,可以考虑从以下两个方面插入相应的printf语句输出过程信息以及响应时间。
线程信号整个响应流程信息输出注重的是任务状态的变化、任务处于哪个队列、任务是怎样进出队列的、等待的线程信号是否发生改变以及在哪里被设置。因此,printf语句应该插入在调用线程信号等待、设置以及任务进出各种列表函数的前后等位置,这样可以输出各种状态信息。
在剖析RTOS线程信号机制的响应时间时,应着重考虑线程信号响应的快慢和耗费的时间长短。在这一过程中,printf语句的执行也需花费一定的执行时间:由于主控芯片STM32L431采用的是48 MHz的内核时钟频率,故通过printf调试手段打印输出一个字符约需77 μs,由此可算出所有printf执行的时间。按照无损检测[9]的要求规定:待检测对象性能的完整性不可以受到所选用的检验技术及检测设备的干扰。因此,此处可以通过代码插桩的方法来测试响应时间性能,即采用变量记录响应时间并在任务获得响应时才利用printf方式输出显示时间信息,而不是在源程序中所有位置都插入printf语句,通过这种方式才可以比较准确地计算出线程信号响应整个过程的时间。将任务执行到线程信号等待语句signal_wait处的时刻设置为T0, 标志线程信号等待开始。将任务执行到线程信号值设置语句signal_set处的时刻设置为T1, 标志线程信号的产生。将任务执行到线程信号存储语句处的时刻设置为T2, 标志该线程信号进入存储待识别阶段。将任务执行到线程信号被识别语句处的时刻设置为T3, 标志该线程信号进入到被识别阶段。将任务执行到线程信号由被识别到进入就绪队列语句处的时刻设置为T4。 最后将任务执行到由就绪队列取出到被RTOS调度语句处的时刻设置为T5。 完成上述时间刻度设置之后,便可以计算出线程信号在各个周期的时间差值:线程信号由产生到存储为 (T2-T1)、 由存储到被识别为 (T3-T2)、 由识别再到响应为 (T4-T3) 以及由等待线程信号到再次被mbedOS[10]调度执行的时间间隔为 (T5-T0)。
3 mbedOS的线程信号响应分析与实践
mbedOS是ARM公司在2014年推出的一款免费的、跨平台的、专为物联网(IoT)中的“事物”而设计的轻量级开源嵌入式操作系统,不仅具备一般RTOS的基本功能,开发设计人员还可以在低成本开发板上快速构建IoT应用原型[11],被广泛应用在物联网设备平台[12]以及通信与安全访问服务机制[13]等领域。下面将通过实践分析mbedOS的线程信号响应机制。
3.1 选择printf插入位置
对线程信号响应机制的分析,主要在于要选择好printf语句的插入位置,这样才能输出响应过程的关键信息。
(1)在线程信号等待语句“Thread::signal_wait(GREEN_SIGNAL)”前后位置加入相应的printf语句,用来显示线程在等待线程信号前和获得线程信号后的关键信息,在该语句之后用T5记录线程被调度的时刻;在线程信号设置语句“thd_greenlight.signal_set(GREEN_SIGNAL)”的前后位置加入相应的printf输出信息,则可以显示设置线程信号值前后的状态变化信息,并在该语句之前用T1记录线程信号产生的时刻。
(2)在“thread->waitFlags=flag”前后位置加入相应的printf语句,用来输出当前线程信号等待标志waitFlags值的变化情况,并在“osRtxThreadDelayInsert(thread, timeout)”语句之前用T0记录线程开始等待线程信号时刻;然后在“threadFlags = threadFlagSet(thread,flag)”这一语句后面加入对应的printf输出语句,并用T2记录线程信号存储的时刻。
(3)在延时等待队列移除线程函数osRtxThreadDelayRemove之前可用T3记录识别到等待线程信号的具体线程的时刻;在线程进队函数osRtxThreadReadyPut之后可用T4记录将等待线程信号的线程放入到就绪队列的时刻。
(4)除此之外,还可以在线程移出函数osRtxThreadWaitExit、线程延时等待函数osRtxThreadWaitEnter等前后位置加入对应的printf输出信息,不仅可以直观地跟踪程序运行状态,还可以显示线程进出各种队列的变化情况。
3.2 响应时间性能及关键代码分析
mbedOS作为一款广泛应用于物联网平台的实时操作系统,其内部通过两种机制来设置线程信号:第一种机制是在某个线程中等待线程信号,在另一线程中通过触发SVC中断来设置线程信号;第二种机制是在某个线程中等待线程信号,而设置具体的线程信号值则是通过PendSV中断机制来实现。为准确测试出线程信号的响应时间,可以在mbedOS测试样例工程中只设定包含两个优先级相同的线程,即蓝灯线程和绿灯线程,并运行在STM32L431微控制器上。mbedOS内部的定时器中断SysTick是通过时间嘀嗒的方式来产生中断,即每个时间嘀嗒(1 ms)可以产生一次中断,对应SysTick中的计数器需要计数48 000次(STM32L431芯片内核时钟频率是48 MHz,计数器采用减1的方式进行计数);而在线程的优先级相同的情况下,mbedOS是利用时间片轮询调度策略来选择某个线程进行调度,即每个时间片大小为5个时间嘀嗒。实时性能的软件测试[14]作为一个设计和考核实时操作系统性能的重要方法之一,主要是通过系统调用的方式来获得操作系统内核中任意两处代码执行的时间间隔。本文采用SVC中断的方式来分析线程信号的响应时间,主要有:线程信号由产生到存储 (T2-T1)、 由存储到被识别 (T3-T2)、 由识别再到响应 (T4-T3) 以及由等待线程信号到再次被mbedOS调度执行的时间间隔 (T5-T0)。 测试方法是在时间嘀嗒中断服务例程SysTick_Handler函数中将全局变量TimerCount(用来记录SysTick中断次数)加1,即先取得TimerCount变量存放的绝对地址,然后给该地址存放的内容执行加1操作再重新赋值给该地址,通过比较不同时刻的Systick中断计数值VAL以及中断次数SUM(由TimerCount变量值的大小决定),采用Δt公式计算求得实际执行时间,即线程信号在某个执行过程需耗费实际时间的计算公式为: Δt=Tend-Tbegin=((VALbegin-VALend)+48000*(SUMend-SUMbegin))/48(μs)。 表1给出了基于SVC中断的线程信号响应时间分析情况,其中 (T2-T1)、 (T3-T2)、 (T4-T3) 的响应时间都较短,在8 μs之内,说明线程信号作为同步与通信手段能满足实时性的要求。而绿灯线程由等待线程信号到再次被调度执行的时间都在5 ms~6 ms之内,则可以说明在线程优先级相同的情况下,mbedOS实时操作系统是采用时间片轮询的方式来对线程进行调度,响应时间同样也比较快,实时性要求能得到满足。
表1 基于SVC中断的线程信号响应时间分析
基于篇幅的有限性,这里仅给出测试线程信号由产生到存储 (T2-T1) 过程中的关键代码,其余各时间段的测试流程分析与此类似。
(1)在时间嘀嗒中断服务例程处理函数SysTick_Handler中设置SysTick中断次数累加的关键代码如下:
SysTick_Handler:
//栈指针(MSP或PSP)和LR(EXC_RETURN)入栈
PUSH {R0,LR}
ldr r2,=0x20001884
ldr r3,[r2]
adds r3,r3,#1
str r3,[r2]
//调用SysTick中断服务例程osRtxTick_Handler
BL osRtxTick_Handler
//R0←堆栈中保存的R0;
//LR←堆栈中保存的LR(EXC_RETURN)
POP {R0,LR}
代码段分析:其中0x20001884是全局变量TimerCount(用来记录SysTick中断次数)编译后的地址,可通过编译后生成的Debug目录文件下的.map文件找到该地址,先将该地址存放的数据赋值给寄存器r3,再将自加1后的数据存放回原地址即可实现每次触发SysTick中断时次数累加1。
(2)在蓝灯线程调用signal_set函数之前记为T1时刻的关键代码:
//T1时刻
n0=TimerCount;
v0=SysTick->VAL;
//设置绿灯信号
thd_greenlight.signal_set(GREEN_SIGNAL);
代码段分析:n0用来记录T1时刻触发的SysTick中断次数;v0则记录T1时刻Systick的计数值VAL, GREEN_SIGNAL是绿灯等待的线程信号值,大小为0x47。这个值的大小可以在宏定义处自己设定。
(3)在SVC实际处理线程信号设置函数svcRtxThreadFlagSet中,线程信号值被赋值给threadFlags变量之后记为T2时刻的关键代码:
//(2)设置线程信号值
threadFlags = ThreadFlagSet(thread, flag);
//T2时刻
n5=TimerCount;
v5=SysTick->VAL;
if(v5>v0)
printf("%d ",v0-v5+(n5-n0)*48000);
else
printf("%d ",v0-v5);
代码段分析:调用ThreadFlagSet函数将对应线程(绿灯线程)的线程信号值设置为0x47,并存储在threadFlags变量中,n5用来记录T2时刻触发的SysTick中断次数;v5则记录T2时刻Systick的计数值VAL。
4 mbedOS的线程信号响应流程
mbedOS线程信号响应机制的测试样例程序是基于Cortex-M4F内核的STM32L431微控制器和STM32CubeIDE 1.0.0集成开发环境进行的。STM32L431采用的是256 KB的片内Flash和64 KB的静态随机存储器SRAM,Flash主要用于程序代码及中断向量表的存储,而片内RAM主要用于各类变量的存储[15]等。芯片采用LQFP-64封装,不仅具有丰富的功能模块:包括GPIO引脚、ADC模块、PWM定时器等,还包含具备强大运算能力的浮点运算单元FPU。STM32L431微控制器不仅包括ARM Cortex-M4F内核以及各种外设、存储器模块,还包含了高性能系统和外设两种总线。另外,STM32L431微控制器还提供可扩展总线用来连接其它外围设备,其结构如图2所示。
图2 STM32L431微控制器结构
4.1 功能设计与流程分析
本文用到的测试工程的功能主要是在mbedOS启动后通过主线程来创建3个相同优先级的用户线程,分别是蓝灯线程、绿灯线程以及红灯线程。然后在绿灯线程中调用signal_wait函数等待绿灯线程信号(GREEN_SIGNAL),从而实现绿灯的亮暗切换;而蓝灯线程则是通过调用signal_wait函数来等待蓝灯线程信号(BLUE_SIGNAL),进而实现蓝灯的亮暗切换;在红灯线程中通过调用signal_set函数分别设置绿灯线程和蓝灯线程的线程等待信号。图3给出了mbedOS测试样例程序的执行流程。
图3 mbedOS测试样例程序的执行流程
在测试程序中,当程序执行到“Thread::signal_wait(GREEN_SIGNAL)”语句时,则表示此时绿灯线程需要等待绿灯线程信号(GREEN_SIGNAL),绿灯线程阻塞被放入到等待队列中。当测试程序执行到“thd_greenlight.signal_set(GREEN_SIGNAL)”语句时,则相当于此时向绿灯线程发送了一个线程信号,绿灯线程收到该信号后,会将之前阻塞的绿灯线程从等待队列移出并放入到就绪队列中,由mbedOS通过时间片轮询的调度策略,将线程状态由阻塞态更改为激活态,并进行上下文切换,然后执行后续的语句,即执行gpio_reverse(LIGHT_GREEN)语句实现切换绿灯亮暗。蓝灯线程的运行流程与绿灯线程一样。
4.2 时序剖析
在STM32L431微控制器的基础上,以测量有关的确定性时序分析[16]方法为例。即在mbedOS测试工程中的对应语句前后位置插入printf来输出信息,图4给出了基于线程信号工作原理的线程调度过程时序图。
结合前面内容分析,可以将线程信号响应的流程分析大致分为以下9个步骤,基于篇幅局限性的原因,本文仅给出与绿灯线程相关的printf输出信息。其中,蓝灯线程的地址是20001774,绿灯线程的地址是20001834,红灯线程的地址是200016B4,定时器线程的地址是2000136C,空闲线程地址是20001328,缺省处理函数DefaultISR的地址是8001A21。而地址200001E4表示等待队列,地址200001D0表示就绪队列。
(1)启动线程
从芯片上电到操作系统的启动,其中包括上电复位及mbedOS启动两大部分,在mbedOS启动后,测试程序会先执行对应的主线程函数app_init,由该函数依次创建红灯、绿灯和蓝灯3个用户线程,接着启动这3个用户线程,然后主线程被阻塞[17]。此时,CPU的控制权交由mbedOS内核,开始对用户线程的调度,即取出并激活就绪队列中优先级最高的红灯线程运行。
(2)绿灯线程等待绿灯信号
mbedOS内部的SysTick中断会每隔1 ms中断一次并按照每个时间片(5 ms)为周期的方式对线程进行轮询调度,此时绿灯线程被激活,并通过执行“Thread::signal_wait(GREEN_SIGNAL)”语句来等待绿灯信号GREEN_SIGNAL(0x47),在执行该语句的过程中,由于绿灯信号此时还未产生,绿灯线程状态会从激活态转换成为阻塞态,并移入等待队列中,同时,从就绪队列中取出优先级最高的红灯线程激活运行。
printf输出结果如下:
2.当前运行的线程=20001834(绿灯)开始。
2-1.当前运行的线程=20001834(绿灯)调用signal_wait(GREEN_SIGNAL)等待线程信号0x47。
2-1-1.设置前当前运行线程=20001834的等待标识=0
5-1.调用osRtxThreadWaitEnter前等待队列=200001E4中的线程: 2000136C->0->8001A21
5-2.调用osRtxThreadWaitEnter前就绪队列=200001D0中的线程: 20001774->200016B4->20001328
6-1.调用osRtxThreadWaitEnter->osRtxThreadDelayInsert将当前运行线程=20001834放到等待队列
6-2.调用osRtxThreadWaitEnter->osRtxThreadListGet从就绪队列获取优先级最高的线程=20001774
6-3.调用osRtxThreadWaitEnter->osRtxThreadSwitch将线程=20001774设置为激活态准备运行
7-1.调用osRtxThreadWaitEnter后等待队列:2000136C->20001834->0
7-2.调用osRtxThreadWaitEnter后就绪队列: 200016B4->20001328->0
(3)蓝灯线程等待蓝灯信号
蓝灯线程通过执行“Thread::signal_wait(BLUE_SIGNAL)”语句来等待蓝灯信号BLUE_SIGNAL(0x42),在执行该语句的过程中蓝灯线程状态由激活态更改为阻塞态,放入到等待队列中,然后取出就绪队列中优先级最高的红灯线程,并将其激活运行。
(4)红灯线程设置绿灯信号
在红灯线程中通过调用“thd_greenlight。signal_set(GREEN_SIGNAL)”函数来设置绿灯信号,此时mbedOS会将绿灯线程由等待队列移出并将其放入到就绪队列中。基于线程优先级相同的原因,此时绿灯线程并不会抢占当前正在运行的蓝灯线程,而是会在SysTick中断中通过轮询调度的方式将绿灯线程激活运行。
printf输出结果如下:
1-1.当前运行的线程=200016B4 (红灯),调用signal_set(GREEN_SIGNAL)设置绿灯等待线程信号0x47。
1-1-1.线程信号设置前的值=0
1-1-2.线程信号设置后的值=47
8-1.调用osRtxThreadWaitExit前等待队列=200001E4中的程:2000136C->20001834->20001774
8-2.调用osRtxThreadWaitExit前就绪队列=200001D0中的线程:20001328->0->8001A21
9-1.调用osRtxThreadWaitExit->osRtxThreadDelayRemove将线程=20001834从等待队列中移出
9-2.调用osRtxThreadWaitExit->osRtxThreadReadyPut->osRtxThreadListPut将线程=20001834放到放到就绪队列
10-1.调用osRtxThreadWaitExit后等待队列:2000136C->20001774->0
10-2.调用osRtxThreadWaitExit后就绪队列=200001D0中的线程:20001834->20001328->0
11.调用signal_set()结束。
(5)轮询调度激活绿灯线程
在蓝灯线程中设置完绿灯信号后,mbedOS内部机制的SysTick中断会每隔1 ms中断一次并按照每个时间片(5 ms)为周期的方式对线程进行轮询调度,此时将激活绿灯线程运行。
printf输出结果如下:
12.进入SysTick_Handler触发osRtxTick_Handler对优先级相同的线程进行轮询调度,将线程=20001834切换为激活态。
(6)绿灯线程获得绿灯信号
绿灯线程在获得绿灯信号后,会从等待队列移出进入就绪队列,然后被激活运行,实现切换绿灯亮暗,即执行“Thread::signal_wait(GREEN_SIGNAL)”后续的语句。然后绿灯线程开始等待下一次的线程信号(即重复4-7步,如图4所示),再激活红灯线程运行。
printf输出结果如下:
2-2.当前运行的线程=20001834(绿灯)已等到线程信0x47,绿灯反转。
2.当前运行的线程=20001834(绿灯)结束。
(7)红灯线程设置蓝灯信号
在红灯线程中通过调用“thd_bluelight.signal_set(BLUE_SIGNAL)”函数来设置蓝灯信号,此时mbedOS会将蓝灯线程从等待队列移出,此时线程状态会由阻塞态更换为就绪态,并放入到就绪队列中。由于mbedOS对优先级相同的线程采用轮询调度策略,此时蓝灯线程并不会抢占当前正在运行的红灯线程,而是会在SysTick中断中通过轮询调度的方式将蓝灯线程激活运行。
(8)轮询调度激活蓝灯线程
在红灯线程中设置完蓝灯信号后,mbedOS内部机制的SysTick中断会每隔1 ms中断一次并按照每个时间片(5 ms)为周期的方式对线程进行轮询调度,此时将会激活蓝灯线程运行。
(9)蓝灯线程获得蓝灯信号
蓝灯线程获得蓝灯信号后执行“Thread::signal_wait(BLUE_SIGNAL)”后续的语句,实现切换蓝灯亮暗。然后蓝灯线程开始新一轮的等待信号(即重复9-13步,如图4所示),再激活红灯线程运行。
5 结束语
本文阐述了mbedOS同步与通信手段——线程信号的响应机制,并在STM32L431微控制器上进行实验测试,通过printf调试手段将线程信号工作原理的整个调度过程信息输出到PC机中,并在mbedOS测试工程中以时序图的方式进行分析总结。可以让读者更加透明地理解线程信号响应的整个脉络结构,不仅有助于从微观的层面来理解RTOS的调度过程。同时,也为进一步剖析RTOS的其它同步与通信方式提供了方法借鉴。后续将进一步对RTOS的其它同步与通信方式进行理解与分析。