2011-04-11 26 views
6

Estoy implementando una comunicación entre 2 procesos utilizando una cola. El problema es que cuando llamo a la función mq_receive, obtengo este error: Mensaje demasiado largo.mq_receive: message too long

he hecho lo siguiente:

struct mq_attr attr; 

long size = attr.mq_msgsize; 
.... // initializing the queue "/gateway" 

int rc = mq_receive(gateway, buffer, size, &prio); 

Si puedo imprimir el valor del tamaño, me sale size = 1, mientras que al imprimir el mismo tamaño pero de otro programa (conseguido por el mismo mecanismo), I conseguir algo no entero largo (-1217186280) ...

¿Cómo puedo solucionar este error? .... así que mientras size = 1, creo que es correcto decir "mensaje demasiado largo" pero ¿por qué es 1?

P.S. También he intentado poner:

int rc = mq_receive(gateway, buffer, sizeof(buffer), &prio); 

pero sin resultado.

+1

¿Está llamando a mq_getattr() allí para obtener el tamaño real? De lo contrario, está haciendo referencia a cualquier basura que esté en la memoria en la ubicación de la estructura. – Duck

+1

Publica el código donde creas la cola e intenta leer de ella. – Duck

Respuesta

6

Al depurar colas POSIX en tiempo real, debe comenzar con un programa de ejemplo que funcione y continuar desde allí. Una vez que tenga el programa de ejemplo ejecutándose, debería ser una simple cuestión de asegurarse de que su propio código siga todos los pasos.

El siguiente programa ha sido probado con éxito bajo Ubuntu 11.04:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <mqueue.h> 

#define MQNAME "/pax" 
#define MQMESG "Hello there!" 

static mqd_t serverUp (void) { 
    int rc; 
    mqd_t svrHndl; 
    struct mq_attr mqAttr; 

    printf ("Bringing up server.\n"); 
    rc = mq_unlink (MQNAME); 
    if (rc < 0) { 
     printf (" Warning %d (%s) on server mq_unlink.\n", 
      errno, strerror (errno)); 
    } 

    mqAttr.mq_maxmsg = 10; 
    mqAttr.mq_msgsize = 1024; 
    svrHndl = mq_open (MQNAME, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR, &mqAttr); 
    if (svrHndl < 0) { 
     printf (" Error %d (%s) on server mq_open.\n", 
      errno, strerror (errno)); 
     exit (1); 
    } 
    printf (" Server opened mqd_t of %d.\n", svrHndl); 
    return svrHndl; 
} 

static void serverReceive (mqd_t svrHndl) { 
    int rc; 
    char buffer[2048]; 
    printf ("Server receiving on mqd_t %d.\n", svrHndl); 
    rc = mq_receive (svrHndl, buffer, sizeof (buffer), NULL); 
    if (rc < 0) { 
     printf (" Error %d (%s) on server mq_receive.\n", 
      errno, strerror (errno)); 
     exit (1); 
    } 
    printf (" Received [%s].\n", buffer); 
} 

static void serverDown (mqd_t svrHndl) { 
    printf ("Bringing down server with mqd_t %d.\n", svrHndl); 
    mq_close (svrHndl); 
} 
static void clientSend (void) { 
    mqd_t cliHndl; 
    int rc; 
    printf ("Client sending.\n"); 
    cliHndl = mq_open (MQNAME, O_RDWR); 
    if (cliHndl < 0) { 
     printf (" Error %d (%s) on client mq_open.\n", 
      errno, strerror (errno)); 
     exit (1); 
    } 
    printf (" Client opened mqd_t of %d.\n", cliHndl); 

    rc = mq_send (cliHndl, MQMESG, sizeof (MQMESG), 1); 
    if (rc < 0) { 
     printf (" Error %d (%s) on client mq_send.\n", 
      errno, strerror (errno)); 
     exit (1); 
    } 

    mq_close (cliHndl); 
} 

int main (void) { 
    mqd_t svrHndl; 

    svrHndl = serverUp(); 
    clientSend(); 
    serverReceive (svrHndl); 
    serverDown (svrHndl); 

    return 0; 
} 

La salida en mi sistema es:

Bringing up server. 
    Server opened mqd_t of 3. 
Client sending. 
    Client opened mqd_t of 4. 
Server receiving on mqd_t 3. 
    Received [Hello there!]. 
Bringing down server with mqd_t 3. 
17

Parece que usted necesita leer los documentos con más cuidado. Cuando llame al mq_receive, debe pasar el tamaño del búfer de destino. Este tamaño debe ser mayor que el atributo mq_msgsize de la cola. Además, parece que tiene un error en la inicialización de los atributos de la cola que hace que la llamada mq_receive sea imposible. Aquí es sesión de colas de mensaje estándar:

  1. Llenar mq_attr estructura (doc):

    struct mq_attr attr; 
    attr.mq_flags = 0; 
    attr.mq_maxmsg = 10; 
    attr.mq_msgsize = 33; 
    attr.mq_curmsgs = 0; 
    
  2. Crear cola con mq_open en proceso maestro (doc):

    mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr); 
    
  3. En escritora proceso cola abierta para escritura:

    mqd_t queue = mq_open(qname, O_WRONLY); 
    

    Y envíe algunos mensajes de texto. Longitud del texto debe ser menor que mq_msgsize atributo de la cola (doc):

    mq_send(queue, "some message", strlen("some message")+1, 1); 
    
  4. En el proceso de lectura de cola abierta para la lectura:

    mqd_t queue = mq_open(qname, O_RDONLY); 
    

    Y luego asignar un almacenamiento intermedio y recibir mensajes. El tamaño del almacenamiento intermedio * debe ser mayor que el atributo mq_msgsize de la cola.Aquí creamos buffer de 50 bytes, mientras que mq_msgsize == 33 (doc):

    char rcvmsg[50]; 
    int iret = mq_receive(queue, rcvmsg, 50, NULL); 
    

Asimismo, recuerda que se debe utilizar para la impresión %ldlong en lugar de %d.

+0

¡gracias por la sólida explicación sobre cómo usar colas de mensajes! – samy

5

No olvide desvincular la cola de mensajes antes de ejecutar su programa de nuevo. Si no lo desenlaza, seguirá utilizando la configuración de la cola de mensajes anterior. Esto sucede cuando finalizas tu programa con Ctrl + C. Creo que es una buena idea poner el siguiente código al principio del programa:

if(mq_unlink(QUEUENAME) == 0) 
    fprintf(stdout, "Message queue %s removed from system.\n", QUEUENAME); 

Una forma alternativa (++ estilo C) que comprueba los errores reales (como permisos) e ignora los casos en que la cola ya existe o no:

int rc = mq_unlink(name.c_str()); 
if (rc != 0 && errno != ENOENT) 
     THROW_ERRNO_EXCEPTION(); 

// ENOENT is the status code if the queue doesn't exist, which is not an error 
// if you are immediately going to create it.