【问题标题】:How to get message and message id from one file to another file?如何从一个文件获取消息和消息 ID 到另一个文件?
【发布时间】:2015-05-25 11:37:16
【问题描述】:

在从 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 时,代码什么也没有返回。你如何解决这个问题?

【问题讨论】:

  • 如果你能更好地缩进你的代码会很有帮助。
  • 你的意思是get.c和send.c需要整理一下吗?还是其中之一?
  • 你应该在问之前做。您想节省一些时间,但是,您会花费更多时间,因为没有人愿意阅读您的代码,也不想提供答案。
  • 我刚刚修复了代码中的基本错误,但我希望 get.c 返回一些打印的东西,而不是什么。

标签: c ipc message-queue


【解决方案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... 是在 if 语句之前的循环内的 printf() 语句中打印的。这表明来自先前中止尝试读取消息的消息正在等待读取。

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

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

课程:

  1. 仔细阅读规范。
  2. 使用一致的结构定义(创建发送方和接收方都使用的标头)。
  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.
$

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多