广东湘恒智能科技有限公司
主营产品: 西门子PLC代理商,plc变频器,伺服电机,人机界面,触摸屏,线缆,DP接头
SIEMENS河北省邢台市 西门子代理商——西门子华北一级总代理

1 消息队列基础

1.1 消息队列的运作机制

创建消息队列时FreeRTOS会先给消息队列分配一块内存空间,这块内存的大小等于消息队列控制块大小加上(单个消息空间大小与消息队列长度的乘积),接着再初始化消息队列,此时消息队列为空。

任务或者中断服务程序都可以给消息队列发送消息,当发送消息时:

如果队列未满或者允许覆盖入队,FreeRTOS会将消息拷贝到消息队列队尾

否则(队列已满),会根据用户指定的阻塞超时时间进行阻塞,在这段时间中,如果队列一直不允许入队,该任务将保持阻塞状态以等待队列允许入队。

当其它任务从其等待的队列中读取入了数据(队列未满),该任务将自动由阻塞态转换为就绪态。

当等待的时间超过了指定的阻塞时间,即使队列中还不允许入队,任务也会自动从阻塞态转移为就绪态,此时发送消息的任务或者中断程序会收到一个错误码err。

发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,发送的位置是消息队列队头而非队尾,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。

1.2 消息队列的阻塞机制

我们使用的消息队列一般不是属于某个任务的队列,在很多时候,我们创建的队列,是每个任务都可以去对他进行读写操作的,但是为了保护每个任务对它进行读写操作的过程,我们必须要有阻塞机制,在某个任务对它读写操作的时候,必须保证该任务能正常完成读写操作,而不受后来的任务干扰。那么,如何实现这个机制呢,其实FreeRTOS已经为我们做好了,每个对消息队列读写的函数,都有这种机制,我称之为阻塞机制。

1.2.1 接收消息

假设有一个任务A对某个队列进行读操作的时候(也就是我们所说的出队),发现它没有消息,那么此时任务A有3个选择:

任务A扭头就走,既然队列没有消息,那我也不等了,干其它事情去,这样子任务A不会进入阻塞态。

任务A还是在这里等等吧,可能过一会队列就有消息,此时任务A会进入阻塞状态,在等待着消息的道来,而任务A的等待时间就由我们自己定义,比如设置1000个系统时钟节拍tick的等待,在这1000个tick到来之前任务A都是处于阻塞态,当阻塞的这段时间任务A等到了队列的消息,那么任务A就会从阻塞态变成就绪态,如果此时任务A比当前运行的任务优先级还高,那么,任务A就会得到消息并且运行;假如1000个tick都过去了,队列还没消息,那任务A就不等了,从阻塞态中唤醒,返回一个没等到消息的错误代码,然后继续执行任务A的其他代码。

任务A死等,不等到消息就不走了,这样子任务A就会进入阻塞态,直到完成读取队列的消息。

1.2.2 发送消息

发送消息操作的时候,为了保护数据,当且仅当队列允许入队的时候,发送者才能成功发送消息

队列中无可用消息空间时,说明消息队列已满,此时,系统会根据用户指定的阻塞超时时间将任务阻塞,在指定的超时时间内如果还不能完成入队操作,发送消息的任务或者中断服务程序会收到一个错误码err,然后解除阻塞状态;

当然,只有在任务中发送消息才允许进行阻塞状态,而在中断中发送消息不允许带有阻塞机制的,需要调用在中断中发送消息的API函数接口,因为发送消息的上下文环境是在中断中,不允许有阻塞的情况。

假如有多个任务阻塞在一个消息队列中,那么这些阻塞的任务将按照任务优先级进行排序,优先级高的任务将优先获得队列的访问权。


展开全文
相关产品
商铺首页 拨打电话 QQ联系 发送询价