【问题标题】:POSIX Message queues, errno 90, message too longPOSIX 消息队列,errno 90,消息太长
【发布时间】:2016-04-29 09:00:50
【问题描述】:

我目前正在使用 POSIX 消息队列做一个最小的 IPC。我有一个管道只能将 uint8_t 作为命令传递,而另一个管道将传递长度不超过 128 个字符的字符串。命令管道工作正常。但是stringpipe总是会给我错误号90,这意味着message too long。我写了一个最小的例子来演示这个问题(请注意:我把它保持在最低限度,所以除了收到错误之外没有任何错误处理)。

#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <stdio.h>

int msg_size = 128;

int send()
{
    struct mq_attr attr = {0, 10, msg_size + 1, 0};
    mqd_t mq = mq_open("/test", O_RDWR | O_CREAT, 00644, &attr);
    char msg[msg_size] = {0};
    strncpy(msg, "this_is_a_test", msg_size);
    mq_send(mq, msg, msg_size, 0);
}

int recv()
{
    struct mq_attr attr = {0, 10, msg_size + 1, 0};
    mqd_t mq = mq_open("/test", O_RDWR | O_CREAT, 00644, &attr);
    char msg[msg_size] = {0};
    int res = mq_receive(mq, msg, msg_size, NULL);
    if (res == -1)
    {
        printf("Errno: %d\n", errno);
    }
    else
    {
        printf("Message: %s\n", msg); 
    }
}

int main()
{
    send();
    recv();
    return 0;
}

编译:

g++ -o mq mq.c -lrt

【问题讨论】:

  • 为什么在没有 C++ 代码的情况下使用 C++ 编译器进行编译?建议使用gcc。编译时,始终启用所有警告。 gcc / g++ 至少使用:-Wall -Wextra -pedantic 我也使用:-Wconversion -std=gnu99。对于贴出的代码,编译器会输出很多警告信息。修复这些警告。
  • 1) 一个消息队列只需要打开一次,与使用该队列的进程数量无关。 2) struct mq_attr 中的实际字段列表取决于实现,因此不能使用初始化程序,而是按字段名称设置每个字段,类似于:mset( &amp;attr, '\0', sizeof( attr ) ); attr.mq_maxmsg = 300; attr.mq_msgsize = MSG_SIZE; attr.mq_flags = 0;

标签: c linux posix


【解决方案1】:

如果您阅读the mq_receive manual page,您会看到EMSGSIZE 的意思是

msg_len小于消息队列的mq_msgsize属性

[强调我的]

确实如此,您将mq_msgsize 属性设置为msg_size + 1,然后您收到msg_size,它比mq_msgsize 属性小一。

在设置mq_msgsize 属性时不需要+1,只需将其删除即可。

【讨论】:

    【解决方案2】:

    以下代码

    1. 干净编译
    2. 确实有效
    3. 您确实需要已创建 /dev/mqueue 设备。
    4. 不要使用已知的系统函数名作为本地函数名
    5. 使用perror() 正确输出错误消息。注意:输出将自动包含与errno相关的系统消息
    6. 注意(size_t)attr.mq_msgsize 在对mq_receive() 的调用中的用法
    7. 注意只需拨打mq_open()一次
    8. 注意mqd_t mqdesstruct mq_attr 变量位于文件全局空间中,因此所有函数都可以看到它们。另一种可能性是将它们作为参数传递。
    9. 请注意,MSG_SIZE 是通过#define 定义的,因此它不会占用堆栈空间或文件全局空间,并且只需要定义一次而不是在每个函数中定义
    10. 不应包含未在代码中使用的头文件。
    11. 请注意,在设置各个字段之前,attr 已全部清除为 0x00
    12. 请注意,在对 mq_send() 的调用中仅指定了消息的实际长度,因此不会发送/接收垃圾

    现在是代码

    #include <fcntl.h>
    #include <sys/stat.h>
    #include <mqueue.h> // mq_open(), mq_send(), mq_receive()
    
    //#include <errno.h>
    //#include <time.h>
    #include <string.h> // strncpy(), strlen()
    
    #include <stdio.h>  // printf(), perror()
    #include <stdlib.h> // exit(), EXIT_FAILURE
    
    #define MSG_SIZE  (128)
    
    static mqd_t mqdes = -1;
    static struct mq_attr attr;
    
    void sendQueue()
    {
        char msg[ MSG_SIZE ] = {0};
        strncpy(msg, "this_is_a_test", MSG_SIZE);
        if( -1 == mq_send(mqdes, msg, strlen(msg), 5) )
        {
            perror( "mq_send failed" );
            exit( EXIT_FAILURE );
        }
    
        else
        {
            printf( "%s\n", "msg sent successfully");
        }
    }
    
    void recvQueue()
    {
        char msg[ MSG_SIZE ] = {0};
    
        ssize_t res = mq_receive(mqdes, msg, (size_t)attr.mq_msgsize, NULL);
        if (res == -1)
        {
            perror("mq_receive failed");
        }
    
        else
        {
            printf("Message: %s\n", msg);
        }
    }
    
    int main( void )
    {
        mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
    
        memset( &attr, 0x00, sizeof(struct mq_attr) );
        attr.mq_maxmsg = 3;
        attr.mq_msgsize = MSG_SIZE;
        attr.mq_flags = 0;
        attr.mq_curmsgs = 0;
    
        char *queueName = "/test";
    
        mqdes = mq_open( queueName, O_RDWR|O_CREAT, mode, &attr);
        if( -1 == mqdes )
        {
            perror( "mq_open failed");
            exit( EXIT_FAILURE );
        }
    
        // implied else, mq_open successful
    
    
        sendQueue();
        recvQueue();
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-21
      • 2020-11-27
      • 2019-03-17
      • 2020-04-18
      • 1970-01-01
      • 2013-03-21
      • 2011-07-10
      • 2014-02-13
      • 2011-06-15
      相关资源
      最近更新 更多