为什么要用:
任务间的通信可以通过全局变量或者信号量来完成。全局变量虽然可以承载通信的内容,但是接收方无法意识到信息的到达,除非发送方向接收方发送一个信号量,或者接收方不断该全局变量;信号量可以立即使接收方知道某个事件的发生,但无法传递具体内容。用信号量进行通信就像我们只拨通别人的手机而不与之通话;用消息队列或者邮箱进行通信则可达到既 拨通别人的手机又与之通话的效果。换句话说,消息队列和邮箱可以及时传送事件的内容。
邮箱通信的机理:
发送方通过内核服务把一封邮件投递到邮箱,内核完成投递任务后通知等待列表中的接收方收取邮件。在整个投递过程中,内核充当了邮递员的角色。这里的“邮件”通常是一个指针,接收方可以通过该指针获取邮件内容。
邮箱的基本操作:
内核通常提供如下的邮箱服务:初始化邮箱的内容。邮箱最初可以包含或者不包含邮件。把邮件发送到邮箱(post)。如果邮箱已满,则返回错误信息
(OS_MBOX_FULL)。以“挂起”方式接收邮件(pend)。如果邮箱为空,则把取信者挂起;若超过一定时间邮箱仍为空,则返回超时信息。
以“非挂起”方式接收邮件(accept)。如果邮箱为空,则返回一个空指针。 当希望一次性向某个任务发送多则消息时,邮箱就有点见肘了。因为一个邮箱只能装一封信。把多上邮箱集中到一起管理和使用就变成了消息队列,所以消息队列的操作和邮箱很相似。可以简单地认为,消息队列是邮箱数组。 如果发送者是一对一的方式发送邮件,则等待列表中的优先级最高的任务将获取邮件;如果是以广播的方式发送邮件,则等待该邮件的所有任务将获得此邮件.
消息队列使用步骤:
1.建立一个指向消息数组的指针和数组的大小,该指针数组必须申明为void类型,如下:
void *MessageStorage[size]
2. 声明一个OS_EVENT类型的指针指向生成的队列,如下:
OS_EVENT *QSem;
3.OSQcreate()函数创建消息队列,如下:
QSem = OSQcreate(&MyArrayOfMsg[0],SIZE);
4.等待消息队列中的消息,OSQPend()
5. 向队列发送一条消息(FIFO),OSQPost();
6.1 向队列发送一条消息(LIFO),OSQPostFront()
6.2 向消息队列发送一则消息(LIFO或者FIFO)
INT8U OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
7、 无等待的从消息队列中获得消息,OSQAccept()
8、 清空消息队列 INT8U OSQFlush (OS_EVENT *pevent)
9、 获取消息队列的状态,OSQQuery()