简体   繁体   English

POSIX消息队列,错误号90,消息太长

[英]POSIX Message queues, errno 90, message too long

I am currently doing a minimal IPC using POSIX Message Queues. 我目前正在使用POSIX消息队列进行最小的IPC。 I have one pipe that only will pass uint8_t 's as commands and another pipe that will pass strings with a length up to 128 characters. 我有一个管道仅将uint8_t作为命令传递,而另一个管道将传递最长为128个字符的字符串。 The command pipe is working fine. 命令管道运行正常。 But the stringpipe will always give me errno number 90, which means message too long . 但是弦管总是给我错误号90,这意味着message too long I have written a minimal example demonstrating the issue (please note: i kept it minimal, so there is no errorhandling whatsoever besides the error upon receiving). 我已经写了一个最小的示例来演示该问题(请注意:我将其保持在最小限度,因此除了接收到错误以外,没有任何错误处理)。

#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;
}

Compile with: 编译:

g++ -o mq mq.c -lrt

If you read the mq_receive manual page you will will see that EMSGSIZE means 如果您阅读mq_receive手册页,您将看到EMSGSIZE意味着

msg_len was less than the mq_msgsize attribute of the message queue msg_len 小于消息队列的mq_msgsize属性

[Emphasis mine] [强调我的]

And that's true, you set the mq_msgsize attribute to msg_size + 1 and then you receive msg_size which is one less than the mq_msgsize attribute. 的确如此,您将mq_msgsize属性设置为msg_size + 1 ,然后收到的msg_sizemq_msgsize属性小一。

You don't need that +1 when setting the mq_msgsize attribute, just remove it. 设置mq_msgsize属性时不需要+1 ,只需删除它即可。

the following code 以下代码

  1. cleanly compiles 干净地编译
  2. actually works 实际有效
  3. You do need to have a /dev/mqueue device already created. 您确实需要已经创建了/dev/mqueue设备。
  4. do not use known system function names for your local function names 不要将已知的系统函数名称用作本地函数名称
  5. use perror() to properly output error messages. 使用perror()正确输出错误消息。 Note: the output will automatically include the system message related to errno 注意:输出将自动包含与errno相关的系统消息
  6. note the usage of (size_t)attr.mq_msgsize in the call to mq_receive() 请注意(size_t)attr.mq_msgsize在对mq_receive()的调用中的mq_receive()
  7. note only need to call mq_open() once 注意只需要调用一次mq_open()
  8. note the mqd_t mqdes and struct mq_attr variables are in the file global space so all the functions can see them. 请注意, mqd_t mqdesstruct mq_attr变量位于文件全局空间中,因此所有函数都可以看到它们。 An alternate possibility is to pass them as parameters. 另一种可能性是将它们作为参数传递。
  9. note the MSG_SIZE is defined via #define so it does not consume space on the stack nor on the file global space and only needs to be defined once rather than in each function 请注意,MSG_SIZE是通过#define定义的,因此它不会占用堆栈空间或文件全局空间,只需要定义一次,而不是在每个函数中定义一次
  10. header files that are not used in the code should not be included. 代码中未使用的头文件不应包括在内。
  11. note the attr is cleared to all 0x00 before setting the individual fields 请注意,在设置各个字段之前, attr清除为全0x00
  12. note that only the actual length of the message is specified in the call to mq_send(), so no trash is sent/received 请注意,在mq_send()的调用中仅指定了消息的实际长度,因此不会发送/接收垃圾

and now the code 现在的代码

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM