2016-04-29 335 views
0

我目前正在使用POSIX消息队列进行最小化的IPC。我有一个管道只能通过uint8_t作为命令,另一个管道将传递长度最长为128个字符的字符串。命令管道工作正常。但是,烟管总是会给我errno数字90,这意味着message too long。我写了一个证明问题的简单例子(请注意:我保持最小限度,所以除了收到错误之外,没有任何错误处理)。POSIX消息队列errno 90消息太长

#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 
+0

为什么在没有C++代码时使用C++编译器进行编译?建议使用'gcc'。编译时,始终启用所有警告。对于'gcc' /'g ++'至少可以使用:'-Wall -Wextra -pedantic'我也使用:'-Wconversion -std = gnu99'。对于发布的代码,编译器将输出许多警告消息。修复这些警告。 – user3629249

+0

1)只需要打开一个消息队列一次,而不管使用该队列的进程数量是多少。 2)'struct mq_attr'中的实际字段列表取决于实现,因此不能使用初始值设定项,而是按字段名设置每个字段,类似于:'mset(&attr,'\ 0',sizeof(attr)) ; attr.mq_maxmsg = 300; attr.mq_msgsize = MSG_SIZE; attr.mq_flags = 0;' – user3629249

回答

1

如果你读the mq_receive manual page你会看到EMSGSIZE意味着

msg_len不是消息队列的mq_msgsize属性少

[重点煤矿]

这是真的,你mq_msgsize属性设置为msg_size + 1然后您会收到msg_size这比mq_msgsize属性少一个。

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

0

下面的代码

  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设置个别字段)
  12. 注意,只有在该呼叫被指定的消息的实际长度,以则mq_send(前被清为所有0×00,所以没有垃圾被发送/接收的

和现在的代码

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