2016-08-18 1 views
2

Ich schrieb ein einfaches C-Programm in Linux, das Nachrichtenwarteschlange für IPC verwendet (ähnlich wie this Post). Zur Vereinfachung werden mq_send und mq_receive im selben Prozess aufgerufen.Senden Puffer variabler Größe über Nachrichtenwarteschlange

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

Ich sende/empfange eine konstante Zeichenfolge mit der Nachrichtenwarteschlange. Jetzt möchte ich das für einen allgemeinen Puffer (Array von Char) wiederholen. Ich sende den Pufferinhalt mit mq_send, aber meine Frage ist, wie mq_receive die genaue Größe des gesendeten Puffers erhalten? Soll ich die Puffergröße separat senden?

Antwort

2

Die schnelle Antwort ist Nein, Sie müssen die Nachrichtengröße nicht separat senden.

Solange die Nachrichtengröße nicht größer als die mq_msgsize Attribut der Warteschlange, die Größe zu mq_send geben wird von mq_received unverändert zurückgegeben.

Sie müssen das '\0' Terminator nicht senden, aber Sie nicht, es wird auch nicht empfangen und der Empfangscode muss es festlegen, um sicherzustellen, dass die empfangene Zeichenfolge null beendet ist. Seien Sie in diesem Fall vorsichtig für ein zusätzliches Byte am Ende des Zielpuffers zu ermöglichen:

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

Für die lange Antwort, müssen Sie überlegen, ob Sie mq_msgsize Attribut Binärmeldungen länger als die maximalen Nachrichtenwarteschlange senden . Wenn Sie dies tun, müssen Sie eine Art Protokoll entwickeln, bei dem Sie der empfangenden Seite mitteilen, wie viele Nachrichten zu erwarten sind und wie sie zu kombinieren sind. Die Länge ist nicht unbedingt erforderlich, aber es wäre bequemer, sie zusammen mit der Anzahl der Nachrichten zu senden, um die Zuweisung auf der Empfangsseite zu vereinfachen.

+0

@ManiAm: erfüllt diese Antwort Ihre Bedürfnisse? Haben Sie noch weitere Fragen? – chqrlie

+0

Danke für die Antwort. Ich stimme zu, dass beim Senden einer Zeichenfolge die Größe nicht gesendet werden muss. Aber in einem allgemeinen Puffer (besteht aus uint8_t) wie der mq_receive wissen, was ist die Größe des Puffers? – ManiAm

+1

@ManiAm: 'mq_send' speichert die Nachrichtenlänge in der Struktur der Nachrichtenwarteschlange und' mq_receive' ruft sie von dort ab. Es spielt keine Rolle, dass Sie eine Zeichenkette senden, 'mq_send' macht keine Annahmen über den Inhalt der Nachricht, es verhält sich für jede Art von Inhalt gleich, sei es 'char',' uint8_t' oder was auch immer. Sie können sogar die Adresse einer Struktur übergeben, solange sie keine Zeiger enthält, da die Zeigerwerte für die Empfangsseite bedeutungslos wären. – chqrlie

Verwandte Themen