2011-04-11 5 views
6

대기열을 사용하는 2 개의 프로세스간에 통신을 구현 중입니다. 문제는 mq_receive 함수를 호출 할 때이 오류가 발생한다는 것입니다. Message too long.mq_receive : 메시지가 너무 깁니다.

나는은 다음 수행 한 : 나는 크기 값을 인쇄하는 경우

struct mq_attr attr; 

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

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

, 내가 얻을 크기 = 1, 나는 같은 크기이지만 (같은 메커니즘에 의해 있어요) 다른 프로그램에서 인쇄 할 때 동안, I (-1217186280) ...

어떻게하면이 오류를 해결할 수 있습니까? ... size = 1 인 동안 "메시지가 너무 길다"라고 말하는 것이 맞지만 왜 1입니까?

P. 나는 또한 넣어려고 :

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

결과가 없습니다.

+1

실제 크기를 얻기 위해 mq_getattr()을 호출하고 있습니까? 그렇지 않으면 구조체의 위치에서 메모리에있는 모든 정크를 참조합니다. – Duck

+1

큐를 작성한 곳의 코드를 게시하고 큐에서 읽으려고하십시오. – Duck

답변

6

실시간 POSIX 대기열을 디버깅 할 때 작동하는 샘플 프로그램부터 시작해야합니다. 샘플 프로그램을 실행 한 후에는 자신의 코드가 모든 단계를 따르는 지 확인해야합니다.

다음 프로그램

우분투 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; 
} 

출력은 다음과 같습니다 좀 더 신중하게 문서를 읽을 필요가 같은

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

보인다. mq_receive에 전화 할 때 대상 버퍼의 크기를 전달해야합니다. 이 크기는 대기열의 mq_msgsize 속성보다 커야합니다. 또한 적절한 mq_receive 호출을 불가능하게 만드는 대기열 속성 초기화에 오류가있는 것 같습니다. 다음은 표준 메시지 큐 세션은 다음과 같습니다

struct mq_attr attr; 
attr.mq_flags = 0; 
attr.mq_maxmsg = 10; 
attr.mq_msgsize = 33; 
attr.mq_curmsgs = 0; 
  • 마스터 과정에서 mq_open와 (doc)를 큐 만들기 : 작가에서

    mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr); 
    
    1. mq_attr 구조체 (doc)를 기입 쓰기 용 프로세스 큐 열기 :

      mqd_t queue = mq_open(qname, O_WRONLY); 
      

      그리고 일부 텍스트를 보내십시오.

      mq_send(queue, "some message", strlen("some message")+1, 1); 
      
    2. 리더 과정 공개 큐에서 읽기 : 텍스트의 길이는 큐 (doc)의 낮은보다 mq_msgsize 속성해야

      mqd_t queue = mq_open(qname, O_RDONLY); 
      

      그리고 버퍼를 할당하고 메시지가 나타납니다. v 퍼 크기 *는 큐의 mq_msgsize 속성보다 커야합니다.

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

    는 또한 인쇄 long 대신 %d에 대한 %ld을 사용한다는 것을 기억 여기에서 우리는 50 바이트 버퍼 동안 mq_msgsize == 33 (doc)를 만들 수 있습니다.

  • +0

    msg 대기열을 사용하는 방법에 대한 확실한 설명에 감사드립니다! – samy

    5

    프로그램을 다시 실행하기 전에 메시지 대기열의 연결을 끊는 것을 잊지 마십시오. 링크를 해제하지 않으면 이전 메시지 대기열 설정을 계속 사용합니다. 이것은 Ctrl + C로 프로그램을 종료 할 때 발생합니다.

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

    또 다른 형태 (C++ 스타일) (권한 등) 실제 오류를 확인하고 어디 큐 이미 케이스를 무시 : 나는 프로그램의 시작 부분에 다음 코드를 삽입하는 것이 좋습니다 생각 존재 여부 :

    관련 문제