预备知识
在VxWorks中实现基于消息队列的C/S通信主要用到了Wind内核中的消息队列API,msgQLib。
这个库里面的发送消息和接受消息的API分别为:
STATUS msgQSend(MSG_Q_ID msgQId, char * buffer, UNIT nBytes, int timeout, int priority)
// 当有任务正在等待某个消息的到来,则被发送的消息立即提交给第一个等待的任务;否则,消息插入消息队列,当消息队列满时,任务被阻塞
int msgQReceive(MSG_Q_ID msgQId, char * buffer, UNIT maxNBytes, int timeout)
// 当有消息在消息队列上,第一个消息被接受;否则调用者被阻塞,进入目标队列的任务队列排队(基于优先级/FIFO)
其中两个函数的timeout参数说明:
- 对于msgQSend,当消息队列满时,发送者被阻塞,等待时间最长为timeout个tick。
- 对于msgQReceive,当消息队列为空时,接受者被阻塞,等待时间最长为timeout个tick。
其中timeout
- 为NO_WAIT,则不等待,立即返回。
- 为WAIT_FOREVER,则一直等待下去,知道队列为非满(对于发送)后非空(对于接受)
- 为某个整形,则等待timeout个ticks,超过时限,则返回。
使用消息队列实现的C/S通信模式示意图为:
很直观吧。这里要明确的一点是,若从空队列读消息或者向满队列发消息的任务都会被阻塞,阻塞的时长由timeout决定。
要想通过消息队列实现两个任务的全双工通信,至少需要两个消息队列。
程序编写
程序设计很简单,但是在设计程序的时候还要明确:Wind内核默认采用基于优先级的抢占式调度(Priority-based preemptive scheduling)。
什么意思呢,系统中每个任务都拥有一个优先级,任意时刻,内核将CPU分给处于就绪态的优先级最高的任务运行,这是“基于优先级的”;一旦内核发现有一个比当前正在运行的任务优先级高的任务就绪,内核立即保存当前任务的上下文,切换到这个高优先级任务的上下文中运行,这是“抢占”,在接下去的程序修改客户端和服务端的优先级导致的运行结果不一致,可以非常直观地看出这一调度策略的运行。
但是这种任务调度策略有缺点啊。假如现在有多个相同优先级