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

How to get message and message id from one file to another file?

在从 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 != '[=10=]'; 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 时,代码 returns 什么也没有。你如何解决这个问题?

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

The argument msgtyp specifies the type of message requested as follows:

  • If msgtyp is 0, the first message on the queue shall be received.

  • If msgtyp is greater than 0, the first message of type msgtyp shall be received.

  • If msgtyp is less than 0, the first message of the lowest type that is less than or equal to the absolute value of msgtyp shall be received.

由于发送进程不是 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... 打印在 if 语句之前循环内的 printf() 语句中。这表明来自先前失败的消息读取尝试的消息正在等待读取。

返回的消息长度为零,因为您在定义消息结构时不够仔细。特别是,接收消息结构使用 int 而不是规范要求的 long,所以在我的机器上 sizeof(int) == 4sizeof(long) == 8 的值是 little-endian, receiver中的字符串相对于sender中的字符串错位,放置了0个字节。修复该问题并传输消息。

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

教训:

  1. 仔细阅读规范。
  2. 使用一致的结构定义(创建一个 header 供发送方和接收方使用)。
  3. 正确定位信号处理代码。
  4. 继续阅读 How to avoid using printf() in a signal handler。在这里会相当安全,但从技术上讲这是未定义的行为,应该避免。

代码: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.
$