2016-08-18 128 views
2

我在Linux中使用IPC的消息隊列(類似於this後)編寫了一個簡單的C程序。爲了簡單起見,在相同的過程中調用mq_sendmq_receive通過消息隊列發送可變大小緩衝區

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <mqueue.h> 

#define QUEUE_NAME "/test_queue2" 

int main(int argc, char **argv) 
{ 
    /* initialize the queue attributes */ 
    struct mq_attr attr; 
    attr.mq_flags = 0; 
    attr.mq_maxmsg = 10; 
    attr.mq_msgsize = 30; 
    attr.mq_curmsgs = 0; 

    /* create the message queue */ 
    mqd_t mq = mq_open(QUEUE_NAME, O_CREAT | O_WRONLY, 0644, &attr); 
    if (mq < 0) { 
     printf("error in mq_open 1"); 
     exit(1); 
    } 

    /* send the message */ 
    int rc = mq_send(mq, "mani123", 8, 0); // need to include the null character too! 
    if (rc < 0) { 
     printf("error in mq_send"); 
     exit(1); 
    } 

    // --------------------------------------------------------------- 

    mqd_t mq2 = mq_open(QUEUE_NAME, O_RDONLY); 
    if (mq2 < 0) { 
     printf("error in mq_open 2: %s", strerror(errno)); 
     exit(1); 
    } 

    char rcvmsg[50]; 
    rc = mq_receive(mq2, rcvmsg, 50, 0); 
    if (rc < 0) { 
     printf("error in mq_receive"); 
     exit(1); 
    } 

    printf("%s", rcvmsg); 

    return 0; 
} 

我使用消息隊列發送/接收常量字符串。現在我想重複這個通用緩衝區(char數組)。我使用mq_send發送緩衝區內容,但我的問題是mq_receive如何獲得發送緩衝區的確切大小?我應該分別發送緩衝區大小嗎?

回答

2

快速回答是不,您不需要單獨發送郵件大小。

只要郵件大小不超過隊列的mq_msgsize屬性時,傳遞給mq_send大小由mq_received返回不變。

您不需要發送終止符,但它不會被接收,它也不會被接收,並且接收代碼必須設置它以確保接收到的字符串是空終止的。在這種情況下,謹慎地允許在目標緩衝區的末尾一個額外的字節:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <mqueue.h> 

#define QUEUE_NAME "/test_queue2" 

int main(int argc, char **argv) { 
    /* initialize the queue attributes */ 
    struct mq_attr attr; 
    attr.mq_flags = 0; 
    attr.mq_maxmsg = 10; 
    attr.mq_msgsize = 30; 
    attr.mq_curmsgs = 0; 

    /* create the message queue */ 
    mqd_t mq = mq_open(QUEUE_NAME, O_CREAT | O_WRONLY, 0644, &attr); 
    if (mq < 0) { 
     printf("error in mq_open 1: %s\n", strerror(errno)); 
     exit(1); 
    } 

    /* send the message */ 
    const char *str = "mani123"; 
    int rc = mq_send(mq, str, strlen(str), 0); // no need to include the null character 
    if (rc < 0) { 
     printf("error in mq_send: %s\n", strerror(errno)); 
     exit(1); 
    } 

    // --------------------------------------------------------------- 

    mqd_t mq2 = mq_open(QUEUE_NAME, O_RDONLY); 
    if (mq2 < 0) { 
     printf("error in mq_open 2: %s\n", strerror(errno)); 
     exit(1); 
    } 

    char rcvmsg[50 + 1]; // 50 is more than enough since attr.mq_msgsize = 30 
    rc = mq_receive(mq2, rcvmsg, 50, 0); 
    if (rc < 0) { 
     printf("error in mq_receive 2: %s\n", strerror(errno)); 
     exit(1); 
    } 
    rcvmsg[rc] = '\0'; 

    printf("received: %s\n", rcvmsg); 

    return 0; 
} 

對於長的答案,你需要考慮你是否會發送二進制消息長於最大消息隊列的mq_msgsize屬性。如果你這樣做,你需要設計一些協議,告訴接收方需要多少條消息以及如何組合它們。長度不一定是必需的,但將它與消息的數量一起發送以簡化接收端的分配會更方便。

+0

@ManiAm:這個答案符合你的需求嗎?您還有其它問題麼? – chqrlie

+0

感謝您的回答。我同意發送字符串時,不需要發送大小。但是在一個通用緩衝區(由uint8_t組成)中,mq_receive如何知道緩衝區的大小是多少? – ManiAm

+1

@ManiAm:'mq_send'將消息長度存儲在消息隊列結構中,'mq_receive'從那裏獲取消息長度。發送一個字符串並不重要,'mq_send'不會對消息的內容做任何假設,對於任何類型的內容(無論是「char」,「uint8_t」還是其他任何內容)都是如此。你甚至可以傳遞一個結構的地址,只要它不包含任何指針,因爲指針值對接收端來說是沒有意義的。 – chqrlie

相關問題