VxWorks 提供了几种不同的任务间通信机制。可使用的不同方法包括:
信号量
信号量是 VxWorks 中的任务间进行同步的主要手段。它提供了三种不同的信号量:二进制信号量、计数信号量和互斥信号量。二进制信号量用于任务间针对临界区域的简单同步。计数信号量允许对代表资源(可以多重方式获取)的临界区域进行多路同时访问。互斥信号量的特别之处在于它能针对基本信号量种类的一些内在问题(包括增加优先级反转保护、删除安全以及对资源的回归访问)提供解决方案。VxWorks 的所有信号量还允许与获取资源有关的超时,以防止无限期等待。
当建立信号量时,程序还能为等待信号量(即将可用)的任务指定唤醒机制。有两种不同的唤醒机制可用:基于优先级的唤醒机制可唤醒优先级最高的任务,而基于先进先出 (FIFO) 的唤醒机制会唤醒等待最久的任务(不考虑其他被阻塞任务的优先级)。VxWorks 还提供对 POSIX 信号量的访问。
信息队列与管道
VxWorks 提供了信息队列作为任务间通信的主要手段。信息队列可保留数量可变的信息,每种信息都有不同的长度。应用程序信息会使用 msgQSend函数在信息队列中排队。在有可用信息之前,接收器会一直封闭。当有可用信息时,会使用以下两种唤醒机制之一唤醒封闭的接收器。基于优先级或先进先出的机制。
VxWorks 的本机信息队列只提供了两种类似的优先级:常规优先级和紧急优先级(信息在发送时会被存放在队列开头) VxWorks 还提供了具有 32 种优先级的 POSIX 信息队列(mq_*)。
管道提供了进程间通信的另一种方式。管道提供了“选择”功能,它允许任务等待来自任何一组文件描述符(输入/输出设备)的数据。QNX Neutrino 提供了符合 POSIX 1003.1 接口规范要求的管道接口实现。
VxWorks 信息队列实例
该实例说明了如何使用信息队列在 VxWorks 中的任务之间实现同步和进行通信。首先,要建立一个会在不同任务间共享的信息队列。这样会产生四种任务:两个发送器任务和两个接收器任务。
#include <msgQLib.h>
#include <stdio.h>
#include <sysLib.h>
#include <string.h>
#include <taskLib.h>
#define MAX_NUM_MSG 5
#define MAX_MSG_LEN 100
#define NUM_MSGS 2*MAX_NUM_MSG
MSG_Q_ID msgQId;
void sendTask1(void)
{
static char buf[MAX_MSG_LEN];
int i;
for (i = 0; i < NUM_MSGS; i++) {
/* Yield to allow other tasks to run. Otherwise FIFO
means that this task will run until blocked. */
taskDelay(0);
/* Write and send a message. */
sprintf(buf, "Send1 %d", i);
if (msgQSend(msgQId, buf, strlen(buf) + 1, WAIT_FOREVER, MSG_PRI_NORMAL) == ERROR) {
printf("Send 1 msgQSend failed!\n");
return;
}
if (i == 3) {
/* Send an urgent message. */
sprintf(buf, "Send1 URG %d", i);
if (msgQSend(msgQId, buf, strlen(buf) + 1, WAIT_FOREVER, MSG_PRI_URGENT) == ERROR) {
printf("Send 1 msgQSend failed!\n");
return;
}
}
}
}
void sendTask2(void)
{
static char buf[MAX_MSG_LEN];
int i;
taskDelay(sysClkRateGet());
for (i = 0; i < NUM_MSGS; i++) {
taskDelay(0);
sprintf(buf, "Send2 %d", i);
if (msgQSend(msgQId, buf, strlen(buf) + 1, WAIT_FOREVER, MSG_PRI_NORMAL) == ERROR) {
printf("Send 2 msgQSend failed!\n");
return;
}
if (i == 5) {
sprintf(buf, "Send2 URG %d", i);
if (msgQSend(msgQId, buf, strlen(buf) + 1, WAIT_FOREVER, MSG_PRI_URGENT) == ERROR) {
printf("Send 2 msgQSend failed!\n");
return;
}
}
}
}
void receiveTask1(void)
{
char buf[MAX_MSG_LEN];
int i;
for (i = 0; i < NUM_MSGS; i++) {
if (msgQReceive(msgQId, buf, MAX_MSG_LEN, WAIT_FOREVER) == ERROR) {
printf("Rx task 1 msgQReceive failed.\n");
} else {
printf("Task 1 received %s\n", buf);
}
}
}
void receiveTask2(void)
{
char buf[MAX_MSG_LEN];
int i;
for (i = 0; i < 10; i++) {
if (msgQReceive(msgQId, buf, MAX_MSG_LEN, WAIT_FOREVER) == ERROR) {
printf("Rx task 2 msgQReceive failed.\n");
} else {
printf("Task 2 received %s\n", buf);
}
}
}
void msgQ_init(void)
{
int pri;
taskPriorityGet(0, &pri);
pri++; /* Priority is less than init’s priority, so init
can run to completion. */
if ((msgQId = msgQCreate(MAX_NUM_MSG, MAX_MSG_LEN, MSG_Q_FIFO)) == NULL) {
printf("msgQCreate failed!\n");
return;
}
if (taskSpawn("task1Tx", pri, 0, 1000, (FUNCPTR) sendTask1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) {
printf("taskSpawn Tx1 failed!\n");
}
if (taskSpawn("task2Tx", pri, 0, 1000, (FUNCPTR) sendTask2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) {
printf("taskSpawn Tx 2 failed!\n");
}
if (taskSpawn("task1Rx", pri, 0, 1000, (FUNCPTR) receiveTask1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) {
printf("taskSpawn Rx 1 failed!\n");
}
if (taskSpawn("task2Rx", pri, 0, 1000, (FUNCPTR) receiveTask2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) {
printf("taskSpawn Rx 2 failed!\n");
}
}