在单CPU中,VxWorks的多任务通信的主要机制是消息队列。如图:
消息队列允许以FIFO方式或给予优先级方式排队消息,消息的数目可变,消息的长度可变。每一个任务都可以向消息队列发送消息也可以从消息队列中读取消息,并且多个任务允许同时从消息队列中收发消息。但是,两个任务间的双向通信通常需要两个消息队列,各自用于一个方向。
VxWorks创建一个消息队列可以使用msgQCreate函数。
函数原型为:MSG_Q_ID msgQCreate(int maxMsgs, int maxMsgLength, int options)
参数说明:
msgQSend() 函数将消息发送到一个消息队列,如果没有任务在等待该队列的消息,那么该消息增加到队列的消息缓冲中;如果此时已经有任务在等待该队列的消息,那么该消息立即提供给第一个等待的任务。
函数原型:STATUS msgQSend( MSG_Q_ID msgQId, char *buffer, UNIT nBytes, int timeout, int priority)
参数解释:
任务使用msgQReceive() 函数从一个消息队列中接收消息,如果该消息队列中已经有可用消息,那么队列中的第一条消息立刻出队,并提交给该任务;如果该队列中没有消息可用,则该任务切换到阻塞状态,并加入到等待该消息的任务队列中。
等待任务队列有两种排序方式,基于优先级或者基于FIFO( 先进先出)方式,由消息队列创建时指定。
函数原型:int msgQReceive (MSG_Q_ID msgQId, char *buffer, UNIT maxNBytes, int timeout)
参数解释:
#incldue "vxWorks.h"
#include "msgQLib.h"
#define MAX_MESSAGES 100
#define MAX_MESSAGE_LENGTH 50
MSG_Q_ID msgQueueId;
static void taskone(void);
static void tasktwo(void);
int main(void)
{
int taskIdone;
int taskIdtwo;
if(NULL == (msgQueueId = msgCreate(MAX_MESSAGES, MAX_MESSAGE_LENGTH, MSG_Q_FIFO)))
{
printf("msgCreaate failed.\n");
}
if(ERROR == (taskSpawn("task1", 90, 0x100, 2000,
(FUNCPTR)taskone, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
{
printf("taskSpawn taskone failed.\n");
}
if(ERROR == (taskSpawn("task2", 90, 0x100, 2000,
(FUNCPTR)tasktwo, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
{
printf("taskSpawn tasktwo failed.\n");
}
return 0;
}
static void taskone(void)
{
char message[] = "Receive Messages from task one.";
if(ERROR == msgQSend(msgQueueId, message, MAX_MESSAGE_LENGTH, WAIT_FOREVER, MSG_PRI_NORMAL))
{
printf("msgQSend in taskone failed.\n");
}
}
static void tasktwo(void)
{
char msgBuf[MAX_MESSAGE_LENGTH];
if(ERROR == msgQReceive(msgQueueId, msgBuf, MAX_MESSAGE_LENGTH, WAIT_FOREVER))
{
printf("msgQReceive in tasktwo failed.\n");
}
else
printf("%s\n",msgBuf);
}
输出结果:
Receive Messages from task one.
上面的程序实现功能非常简单,在主任务中创建了一个信号量并且创建了两个分支任务taskone和tasktwo,任务taskone 往消息队列中写入一个消息message,内容为”Receive Messages from task one.”,任务tasktwo则从消息队列中读取内容并将其输出到屏幕打印显示出来。
通过这个简单的实例程序明白了任务间的通信方式。