VxWorks消息队列

本文介绍VxWorks系统中消息队列的基本概念及其实现机制,包括创建、发送和接收消息的操作,并通过示例代码展示如何进行任务间通信。

VxWorks消息队列

在单CPU中,VxWorks的多任务通信的主要机制是消息队列。如图:
Alt text

消息队列允许以FIFO方式或给予优先级方式排队消息,消息的数目可变,消息的长度可变。每一个任务都可以向消息队列发送消息也可以从消息队列中读取消息,并且多个任务允许同时从消息队列中收发消息。但是,两个任务间的双向通信通常需要两个消息队列,各自用于一个方向。

相关控制函数

msgQCreate()

VxWorks创建一个消息队列可以使用msgQCreate函数。
函数原型为:MSG_Q_ID msgQCreate(int maxMsgs, int maxMsgLength, int options)
参数说明:

  • maxMsgs:消息队列长度( 消息队列中消息的个数 )
  • maxMsgLength:消息队列中消息的最大长度
  • 等待Task的排队方式,可为FIFO 或者 PRIORITY
    这里写图片描述

msgQSend()

msgQSend() 函数将消息发送到一个消息队列,如果没有任务在等待该队列的消息,那么该消息增加到队列的消息缓冲中;如果此时已经有任务在等待该队列的消息,那么该消息立即提供给第一个等待的任务。
函数原型:STATUS msgQSend( MSG_Q_ID msgQId, char *buffer, UNIT nBytes, int timeout, int priority)
参数解释:

  • msgQId :消息队列ID
  • buffer: 要发送的消息(字符串)
  • nBytes:消息长度
  • timeout:超时时间,单位为ticks,可设为NO_WAIT 或WAIT_FOREVER
  • priority:优先级,可设为MSG_PRI_NORMAL 或MSG_PRI_URGENT

msgQReceive()

任务使用msgQReceive() 函数从一个消息队列中接收消息,如果该消息队列中已经有可用消息,那么队列中的第一条消息立刻出队,并提交给该任务;如果该队列中没有消息可用,则该任务切换到阻塞状态,并加入到等待该消息的任务队列中。
等待任务队列有两种排序方式,基于优先级或者基于FIFO( 先进先出)方式,由消息队列创建时指定。
函数原型:int msgQReceive (MSG_Q_ID msgQId, char *buffer, UNIT maxNBytes, int timeout)
参数解释:

  • msgQId:消息队列ID
  • buffer:接收消息存放的位置
  • maxNBytes:接收消息缓冲的字节数
  • 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则从消息队列中读取内容并将其输出到屏幕打印显示出来。
通过这个简单的实例程序明白了任务间的通信方式。

VxWorks操作系统中,`msgQReceive`函数用于从消息队列中接收消息。该函数的返回值76对应于特定的错误代码,表示**消息队列为空**(即没有可用的消息可以接收)[^1]。 ### 可能的原因 1. **消息队列中无消息** 调用`msgQReceive`时,如果消息队列中没有任何待处理的消息,则会返回76。这种情况通常发生在消费者线程或任务尝试读取消息时,而生产者尚未发送任何消息到队列中。 2. **超时设置为0且队列为空** 如果调用`msgQReceive`时指定的超时时间为0,并且此时队列为空,则函数不会等待,而是立即返回错误代码76。 3. **同步问题** 在多任务环境中,可能存在任务间同步问题,导致期望接收到的消息未被正确发送至队列中。例如,接收任务可能在发送任务有机会写入消息之前就尝试读取。 4. **逻辑错误或资源竞争** 如果多个任务同时访问同一个消息队列,但未正确使用互斥机制(如信号量),可能会导致队列状态不一致,进而出现意外的返回值。 5. **消息队列初始化失败或配置错误** 如果消息队列未正确初始化或配置不当(如消息大小、最大消息数等参数设置错误),也可能导致后续的`msgQReceive`调用无法正常工作。 ### 处理建议 - **检查调用逻辑**:确保在调用`msgQReceive`之前,已有任务或线程向队列中发送了消息。 - **合理设置超时时间**:如果希望在队列为空时等待一段时间,可以将超时参数设为正值,避免立即返回错误。 - **调试与日志记录**:在关键位置添加日志输出,跟踪消息的发送与接收过程,帮助定位问题。 - **验证队列初始化**:确认消息队列的创建和初始化过程是否成功,相关参数是否符合预期。 ### 示例代码 以下是一个简单的示例,展示如何使用`msgQReceive`并处理其返回值: ```c #include <vxWorks.h> #include <msgQLib.h> #include <stdio.h> #define MAX_MSGS 10 #define MSG_SIZE sizeof(int) MSG_Q_ID msgQId; void sender() { int msg = 42; if (msgQSend(msgQId, &msg, MSG_SIZE, NO_WAIT) == ERROR) { printf("Failed to send message\n"); } } void receiver() { int rcvMsg; STATUS status = msgQReceive(msgQId, &rcvMsg, MSG_SIZE, WAIT_FOREVER); if (status == ERROR) { int errnoVal = errnoGet(); if (errnoVal == S_objLib_OBJ_UNAVAILABLE) { printf("Message queue is empty (error code: %d)\n", errnoVal); } else { printf("Error receiving message: %d\n", errnoVal); } } else { printf("Received message: %d\n", rcvMsg); } } ``` 在上述代码中,`receiver`函数会尝试从消息队列中接收消息。如果队列为空且设置了`WAIT_FOREVER`,则会一直阻塞直到有消息到达;否则,可以根据返回值和`errno`进行相应的错误处理。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值