RTOS中消息、信号量、互斥量、事件使用区别(类比理解)
注:本文仅代表本人学习中的理解,未必正确,欢迎指正!
1、消息
1.1 对FreeRTOS
就像往火车上装货卸货,默认从前往后装,卸货按照先入先出原则,也就是从第一节车厢开始。紧急时,装货可装入上次卸货的车厢,这样可以被优先卸货。如果多个人同时要卸货,那么按照优先级排队,优先级高的先卸。
四个重要的指针及初始位置:pcWriteTo(装货位置,初始指向第一节),u.pcReadFrom(卸货位置,初始指向最后一节),pcHead(指向第一节),pcTail(指向最后一节往后的空地)。消息传递过程中,主要对前两个通过前两个指针的动作来完成。
1.2 对RT-Thread
就像两列火车,车厢可拆卸,一列(简称A列车)都是空的车厢,另外一列(简称B列车)都是已装货的车厢。消息队列刚创建时,只有一列都是空的车厢。发送一个消息就是从空的列车上取下最后一节车厢,装上货,然后这节车厢移到B列车(第一次时,B列车一节车厢都没有,移过来的就是第一节)。再次发送消息,再从A列车取出最后一节,装上货,移到B列车的后面做为尾巴。依次类推。接收消息就是卸货,从B列车的第一节车厢开始(先进先出)卸完货,然后将这节车厢移到A列车的尾巴上,这样B列车原来排第二节的车厢就变成了第一节。接收方只有从B列车卸货后(也就是必须B列车必须有货)才能往下执行。依次类推。
消息的作用:用于同步,比如接收方(A任务)必须拿到消息队列里的消息才能执行后续操作,否则就任务A就会处于挂起状态(如果使能延时等待)或直接返回错误(如果设置不等待)。发送方(任务B)发送消息到消息队列,如果消息队列已经满了,那么任务B会挂起(如果设置延时等待)或返回错误(如果设置不等待)。看起来像是A在等待B,实际上他们是独立的,他们的实际联系对象是消息队列。这里要注意的是,RT-Thread的消息队列只有接收支持阻塞机制,发送方不会被阻塞,如果队列已满,会得到一个错误代码,但不会被阻塞,这一点跟FreeRTOS是不一样的。
2、信号量
信号量也是用于同步,但是与消息不同的是,信号量不带内容。直观来说,信号量可以比喻为容器里的小球,发送方负责往容器里扔球,获取方负责从容器取球,获取方取到球了才能执行后续任务,否则延时等待或返回失败代码,就这么简单。信号量分为二值信号量和计数信号量。二值信号量就是说,容器里只能容纳一个球,发送方无论往里扔多少次(如果有了还能扔成功吗?),最终容器里都只有一个。计数信号量可以容纳N个球(建立信号量的时候约定N的值),容器最多可以包含N个球,如果多了就扔不进去了。
对于信号量,接收方接收一次容器就会少一个球,如果是二值信号量,接收后,容器里就只有0个球了。
3、互斥量
互斥量跟二值信号量非常像,也是容器里只能包含一个球。但是互斥量具有优先级继承机制,使得互斥量更多用于临界资源访问(信号量更常用于任务间同步)。互斥量的使用也有点区别,通常是获取和释放成对使用(这看起来是不是很像访问临界资源时临时关闭和开启中断啊),而信号量更常用的是一个任务发送,一个任务获取。
另外,互斥量有优先级继承机制,什么意思呢,例如有任务L(低优先级)、任务M(中优先级)、任务H(高优先级)三个任务,任务L和任务H共同需要互斥量,任务M不需要互斥量。假如任务L最先获取了互斥量(占用了资源),此时如果任务H和任务M也就绪了,那么,为了避免任务L占用了互斥量但还未释放的时候先去执行任务M而非任务H(因为任务H需要等待任务L将互斥量释放才能得以运行,而任务M不需要互斥量,只要就绪就能因它比任务L优先级高而马上得到运行),系统会临时提高任务L的优先级跟任务H一样高,这样,就能保证先让占用互斥量的任务L运行完(运行完后会回到低优先级),再运行任务H,再运行任务M,如果没有优先级继承机制,就会产生任务M比任务H先运行的情况,如果正好任务M运行时间很长,那就麻烦了,任务H要等很久才能运行,显然跟我们对高优先级的设置初衷不一样了。
4、事件
事件跟消息比较像,也是用于同步,不同的是,事件不传送数据,而消息可以传送数据。事件更简单,实际上裸机程序中,我们就经常使用类似的方法来判断事件是否发生。事件更像是一排拨码开关(事件组),每个事件代表一位开关。比如有任务P(判断方)、任务S1(设置方)、任务S2(设置方),任务S1发送或设置事件1,任务2发送或设置事件2,任务P对这些事件进行判断,条件成立才可以执行后续任务。任务P可以灵活设置条件,可以是任一事件发生就成立(or)、或者全部事件发生才成立(and)。任务P也可以设置是否读取后清除事件,一般设置为使能清除。一般情况下这样使用事件,事件1和事件2都成立,触发任务P条件成立,任务P判断条件成立后自动清除事件1和事件2,然后执行下面的程序。下一次,重新等待事件1和事件2再次发生。
5、任务通知(FreeRTOS)和邮箱(RT-Thread)
FreeRTOS的任务通知(以下简称任务通知)和RT-Thread的邮箱(以下简称邮箱)比较类似,其特点是只能发送固定32位的数据(如果要发送长数据,可以发送一个32位的指针,该指针指向一个数组),相比较消息队列,其RAM更小,效率更高。
不过,任务通知和邮箱也有各自的特点。任务通知的特点是不需要专门建立数据结构和申请内存,任务通知的字段本身存在于任务控制块中,但是其缺点是只有接收方可以阻塞,发送方不能阻塞,很多场合下都可以直接替换消息、信号量和事件。邮箱看起来更像是简化版的消息,其运作机制也跟消息队列几乎一样,唯一区别就是只能发送固定32位的数据。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)