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

C 两个分叉进程之间的消息队列导致来自msgsnd的参数无效,c,fork,posix,message-queue,C,Fork,Posix,Message Queue,该程序创建两个子进程。第一个子进程(1)从stdin读取文本,删除任何特殊字符,并将其拆分为单词。程序的这一部分工作得很好。然后,当子级(1)拆分单词时,它通过消息队列发送整个单词。此部分导致无效参数错误。然后,孩子2应该将收到的信息打印回屏幕 至少我是这样计划的。我有点卡住了,不知道如何调试消息队列。现在它正在抛出一个错误 #include <signal.h> #include <stdio.h> #include <string.h> #include

该程序创建两个子进程。第一个子进程(1)从stdin读取文本,删除任何特殊字符,并将其拆分为单词。程序的这一部分工作得很好。然后,当子级(1)拆分单词时,它通过消息队列发送整个单词。此部分导致无效参数错误。然后,孩子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 fork\n");
      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 %s\n", message2.msg);
      break;

    case -1:
      perror("error fork\n");
      break;

    default:
      wait(NULL);
      break;
  }

  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义队列\u PERMS 0644
静态int消息_队列=(int)0;
静态键=0;
typedef结构消息
{
长型;
char-msg[100];
}混乱;
int main(int argc,char*argv[]){
常量字符分隔符[]=“,.-!?()1234567890@$%^&*\n”;
char*word=NULL;
缓冲区大小=100;
字符*令牌;
混乱信息;
混乱信息2;
int i;
//设置消息队列
key=ftok(_文件,'x');
//创建队列
消息队列=msgget(密钥、队列管理、IPC创建);
如果(消息队列==-1){
perror(“创建消息队列”);
}
//创建parcer进程。这将标记字符串
//并将每个工作发送到排序功能
开关(fork()){
案例0:
//子进程#1从这里开始
key=ftok(_文件,'x');
消息队列=msgget(密钥、队列队列);
//在这里把单词分开,这样做很好
while(getline(&word,&buffer,stdin)!=EOF){
token=strtok(字、分隔符);
while(令牌!=NULL){
对于(i=0;令牌[i];i++){
令牌[i]=tolower(令牌[i]);
}
//将类型设置为1以发送
message.mtype=1;
//将单词(令牌)复制到消息结构
strcpy(message.msg,token);
//****我收到发送失败:此处的参数无效*****
如果(msgsnd(键和消息、sizeof(消息)、MSG_NOERROR)=-1){
perror(“发送失败”);
}
token=strtok(空,分隔符);
}
}    
打破
案例1:
perror(“错误叉\n”);
打破
违约:
等待(空);
打破
}
//此过程应读取消息并将其打印出来
开关(fork()){
案例0:
//子进程2从这里开始
key=ftok(_文件,'x');
消息队列=msgget(密钥、队列队列);
msgrcv(键和消息2、消息大小、消息1、消息无错误);
printf(“子进程得到%s\n”,message2.msg);
打破
案例1:
perror(“错误叉\n”);
打破
违约:
等待(空);
打破
}
返回0;
}

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

msgrcv()
也有同样的问题

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

$ ./mq
abelone apathy
child process got abelone
child process got apathy
$
我在一行中输入了
abelone apathy
,然后用Control-D表示EOF


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

您可以使用
msgget()
设置
消息队列
的消息队列ID,然后尝试使用
键而不是消息队列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\u queue

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

(1)将错误的值设置为
msgsnd/msgrcv
。在代码中使用
msgget
的返回值,即
message\u queue


(2) 您的
fork
代码错误。父级将创建一个子级,然后点击
wait
,在第一个子级死亡之前等待,然后继续创建第二个子级。在switch语句中仅使用了
break
的某些地方,您需要重新考虑使用
exit

一个建议:使用函数封装发送方和接收方的操作。然后,您可以简化
main()
函数,以便它只在正确的点调用这些函数。你的代码很好;它通过了我的编译测试(
gcc-g-O3-std=c99-Wall-Wextra-Wmissing prototype-Wstrict prototype-Wold样式定义-Wold样式声明-Werror mq.c-o mq
)(