如何从一个文件到另一个文件获取消息和消息ID?

时间:2015-05-25 11:37:16

标签: c ipc message-queue

从send.c发送消息和进程ID后,如何从get.c文件中的消息队列中获取消息?

来自send.c的

 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 #define   MAX_COUNT  200
 #define   BUF_SIZE   100
 #define MSGSZ     255
 #define KEY 10
  //from http://www.tldp.org/LDP/LG/issue89/misc/raghu/send.c.txt
  /*
   * Declare the message structure.
   */
    typedef struct msgbuf {
     long    mtype;
     char    mtext[MSGSZ + 1];
     } message_buf; 

     static message_buf sbuf;
      static size_t buf_length;
     static int mqid;  

      int main(int argc, char*argv[])
      {
      pid_t  pid;
      int    i;
      char   buf[BUF_SIZE];

    if ((pid = getpid()) < 0) { //getting child process id
     perror("unable to get pid \n");
     } 
      else {
    printf("The process id is %d \n", pid);
    }

       char line[256];
      int c = 0;  //for character count 

     printf("enter word/s (must be less than or equal 256 characters): \n");
     fgets(line, 256, stdin);

     printf("\n");
     if ( c > 256 )
     {
     printf("Must enter less than or equal to 256 characters.");
     printf("Has %d characters", countChar(line)); 
      exit(0);
      }

      (void) strcpy(sbuf.mtext, line);
       buf_length = strlen(sbuf.mtext) + 1;

        sbuf.mtype = pid; 
        logMessage(sbuf.mtype, line);     
     }

     int countChar(char *s) 
     { 
     int len = 0; 
     for(; *s != '\0'; s++, len++); 
       return len; 
      }

     int logMessage(int serviceId,char*message)
    {
    int rv, mask, msgid;  
    key_t key = KEY;
    mask = 0644|IPC_CREAT;
    msgid = msgget(key, mask);

if (msgsnd(msgid, &sbuf, buf_length, IPC_NOWAIT) < 0) //sending message
{
 perror("msgsnd");
 exit(1);
 }
 else
 {
 printf("id - %d : message - %s \n", serviceId, message);
 }

return rv;
  }
来自get.c的

  #include <stdio.h>
  #include <stdlib.h>
  #include <signal.h>
  #include <sys/msg.h>
  #include <sys/ipc.h> 
  #include <stdarg.h>
  #include <sys/types.h>
  #include <unistd.h>
  #include <errno.h>
  #include <string.h>
  #define MSGSZ    255
  #define MSGCHARS     255
  #define KEY 10

 typedef struct msgbuf
 {
int mtype;
char mtext[MSGSZ]; 
}message_buf;

static int queue_id;
void     INThandler(int);

 int main(int argc, char*argv[])
{
 key_t key = KEY
message_buf  rbuf;
 int msgflg = 0644;
int msqid = msgget(key, msgflg);

if (msqid < 0) {
    perror("msgget");
    exit(1);
}    
  rbuf.mtype = 1;
  for(;;){
 if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) {
    perror("msgrcv");
    exit(1);
   }
   printf("id - %d : message - %s ", rbuf.mtype, rbuf.mtext);
   } 

     signal(SIGINT, INThandler);//the function starts with ctrl+c. 
     while (1)
      pause();

return 0;
}

  void  INThandler(int sig)//this function  deletes the message queue
  {
 signal(sig, SIG_IGN);
 int mask, msgid;
 key_t key = KEY;
mask = 0644;
msgid = msgget(key, mask);  

if (msgid == -1) {
    printf("Message queue does not exist.\n");
    exit(EXIT_SUCCESS);
}

if (msgctl(msgid, IPC_RMID, NULL) == -1) {
    fprintf(stderr, "Message queue could not be deleted.\n");
    exit(EXIT_FAILURE);
}
    else {
printf("Message queue was deleted.\n");
    }
    exit(0);
return EXIT_SUCCESS;  
}

我能够从send.c成功发送进程id和消息,但是当执行get.c时,代码什么都不返回。你是怎么解决的?

1 个答案:

答案 0 :(得分:1)

您的问题由msgrcv()的POSIX规范确定。 msgtyp参数是第四个参数,在代码中指定为1

  

参数msgtyp指定请求的消息类型,如下所示:

     
      
  • 如果msgtyp为0,则应收到队列中的第一条消息。

  •   
  • 如果msgtyp大于0,则应收到msgtyp类型的第一条消息。

  •   
  • 如果msgtyp小于0,则应收到小于或等于msgtyp绝对值的最低类型的第一条消息。

  •   

由于发送过程不是init过程,因此从来没有来自PID = 1的消息。只需更改您的来电:

if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0)

if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0)

意味着接收器的下一次运行得到了:

Waiting...
id - 60464 : message -  Waiting...
id - 60478 : message -  Waiting...
id - 60482 : message -  Waiting...
id - 71796 : message -  Waiting...

其中Waiting...printf()语句之前的循环内的if语句中打印。这表明先前中止尝试阅读邮件的消息等待阅读。

消息返回为零长度,因为您在定义消息结构时没有足够小心。特别是,接收消息结构使用int而不是规范要求的long,因此在我的sizeof(int) == 4sizeof(long) == 8并且值为little-endian的机器上,接收器中的字符串相对于发送器中的字符串放错位置,并放置0个字节。解决这个问题并传输消息。

请注意,中断处理程序设置不够早;它实际上从未在原始代码中使用过。

经验:

  1. 仔细阅读说明书。
  2. 使用一致的结构定义(创建发送方和接收方使用的标头)。
  3. 正确定位信号处理代码。
  4. 阅读How to avoid using printf() in a signal handler。它在这里相当安全,但它在技术上是未定义的行为,应该避免。
  5. 代码:send.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <unistd.h>
    
    #define MSGSZ   255
    #define KEY     10
    
    typedef struct msgbuf
    {
        long mtype;
        char mtext[MSGSZ+1];
    } message_buf;
    
    int main(void)
    {
        message_buf sbuf;
        sbuf.mtype = getpid();
    
        printf("The process id is %ld\n", sbuf.mtype);
    
        printf("enter word/s (must be less than %d characters):\n", MSGSZ+1);
        if (fgets(sbuf.mtext, sizeof(sbuf.mtext), stdin) == 0)
        {
            printf("EOF detected\n");
            exit(EXIT_FAILURE);
        }
    
        printf("\n");
    
        key_t key = KEY;
        int mask = 0644 | IPC_CREAT;
        int msgid = msgget(key, mask);
        if (msgid < 0)
        {
            fprintf(stderr, "Failed to create msg key %d\n", key);
            exit(EXIT_FAILURE);
        }
    
        if (msgsnd(msgid, &sbuf, strlen(sbuf.mtext)+1, IPC_NOWAIT) < 0)
        {
            perror("msgsnd");
            exit(EXIT_FAILURE);
        }
    
        printf("id - %ld : message - %s\n", sbuf.mtype, sbuf.mtext);
    
        return 0;
    }
    

    代码:recv.c

    #include <errno.h>
    #include <signal.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <unistd.h>
    
    #define MSGSZ    255
    #define KEY 10
    
    typedef struct msgbuf
    {
        long mtype;
        char mtext[MSGSZ+1];
    } message_buf;
    
    static void INThandler(int);
    
    int main(void)
    {
        key_t key = KEY;
        int msgflg = 0644;
        message_buf rbuf;
    
        int msqid = msgget(key, msgflg);
    
        if (msqid < 0)
        {
            perror("msgget");
            exit(1);
        }
    
        signal(SIGINT, INThandler);
    
        rbuf.mtype = 1;
        for ( ; ; )
        {
            printf("Waiting...\n");
            ssize_t nbytes = msgrcv(msqid, &rbuf, MSGSZ, 0, 0);
            if (nbytes < 0)
            {
                perror("msgrcv");
                exit(1);
            }
            printf("id - %ld : message (%d) - %s", rbuf.mtype, (int)nbytes, rbuf.mtext);
        }
    
        return 0;
    }
    
    static void  INThandler(int sig)
    {
        signal(sig, SIG_IGN);
        int mask, msgid;
        key_t key = KEY;
        mask = 0644;
        msgid = msgget(key, mask);
    
        if (msgid == -1)
        {
            printf("Message queue does not exist.\n");
            exit(EXIT_SUCCESS);
        }
    
        if (msgctl(msgid, IPC_RMID, NULL) == -1)
        {
            fprintf(stderr, "Message queue could not be deleted.\n");
            exit(EXIT_FAILURE);
        }
        else
            printf("Message queue was deleted.\n");
        exit(0);
    }
    

    样品运行

    $ ./send <<< "The message to be sent."
    The process id is 71901
    enter word/s (must be less than 256 characters):
    
    id - 71901 : message - The message to be sent.
    
    $ ./send <<< "Another message to be sent."
    The process id is 71902
    enter word/s (must be less than 256 characters):
    
    id - 71902 : message - Another message to be sent.
    
    $ ./send <<< "A third message sent to the receiver."
    The process id is 71903
    enter word/s (must be less than 256 characters):
    
    id - 71903 : message - A third message sent to the receiver.
    
    $ ./recv
    Waiting...
    id - 71901 : message (25) - The message to be sent.
    Waiting...
    id - 71902 : message (29) - Another message to be sent.
    Waiting...
    id - 71903 : message (39) - A third message sent to the receiver.
    Waiting...
    ^CMessage queue was deleted.
    $