两个分叉进程之间的消息队列导致msgsnd的参数无效



程序创建两个子进程。第一个子进程(1)从stdin读取文本,删除任何特殊字符,并拆分为单词。这部分程序运行得很好。然后,当child(1)拆分单词时,它通过消息队列发送每个完整的单词。这部分导致无效参数错误。Child 2应该把它得到的消息打印回屏幕。

至少我是这么计划的。我有点卡住了,不确定如何调试消息队列。现在它从

抛出一个错误
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h> 
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <ctype.h>
# define QUEUE_PERMS 0644
static int message_queue = (int) 0;
static key_t key = (key_t) 0;
typedef struct message
{
  long mtype;
  char msg[100];
} mess_t;
int main(int argc, char *argv[]){
  const char delimiters[] = " ,.-!?()1234567890@#$%^&*n";
  char *word = NULL;
  size_t buffer = 100;
  char *token;
  mess_t message;
  mess_t message2;
  int i;

  // set up a message queue
   key = ftok(__FILE__,'x');
  // create queue
   message_queue = msgget(key, QUEUE_PERMS | IPC_CREAT);
   if(message_queue == -1){
    perror("creating message queue");
   }
  // create parcer process. This tokenizes the strings
  // and send each work to the sort function(s)
  switch(fork()){
    case 0:
      // child process # 1 starts here
      key = ftok(__FILE__,'x');
      message_queue = msgget(key, QUEUE_PERMS);
      // splitting the words up here, this works fine 
      while(getline(&word, &buffer, stdin) != EOF){
        token = strtok(word, delimiters);
        while(token != NULL){
          for(i = 0; token[i]; i++){
            token[i] = tolower(token[i]);
          }
          // set type to 1 to send
          message.mtype = 1;
          // copy the word (token) over to the message struct
          strcpy(message.msg,token);
          // **** I get a send failed: Invalid argument here  *****
          if(msgsnd(key, &message, sizeof(message), MSG_NOERROR) == -1){
            perror("send failed");
          }
          token = strtok(NULL, delimiters);
        }
      }    
      break;
    case -1:
      perror("error forkn");
      break;
    default:
      wait(NULL);
      break;
  }
  // this process should read the message an print it out
  switch(fork()){
    case 0:
    // child process # 2 starts here
      key = ftok(__FILE__,'x');
      message_queue = msgget(key, QUEUE_PERMS ); 
      msgrcv(key, &message2, sizeof(message),1, MSG_NOERROR); 
      printf("child process got %sn", message2.msg);
      break;
    case -1:
      perror("error forkn");
      break;
    default:
      wait(NULL);
      break;
  }
  return 0;
}

您使用msgget()设置message_queue消息队列ID,但随后尝试使用key而不是消息队列ID发送给msgsnd()

msgrcv()也有同样的问题。

当我修复这两个,我可以运行程序:

$ ./mq
abelone apathy
child process got abelone
child process got apathy
$

我在一行输入abelone apathy,然后输入Control-D表示EOF。

在组织好之后,在启用读进程之前,写进程将填充消息队列。只要输入不是太大,就可以。但是,您可能真的希望这两个进程并发运行。您需要移动wait()调用以提供并发性。(正确地将代码分成函数的另一个好处—如果您尽可能地隐藏,则更容易发现此类问题。

(1) msgsnd/msgrcv值错误。在代码中使用msgget的三个返回值,即message_queue

(2)你的fork代码是错误的。父进程将创建一个子进程,然后点击wait,等待第一个子进程死亡,然后继续创建第二个子进程。您将需要重新考虑在某些地方使用exit,您只是在交换机语句中使用break

最新更新