简体   繁体   中英

Message queue between two forked processes causing invalid argument from msgsnd

The program creates two child processes. The first child process (1) reads text from stdin, removes any special chars, and spilts into words. That part of the program works just fine. Then while child (1) is splitting up the words it is sending each whole word through a message queue. This part causes the invalid argument error. Child 2 should then just print the message it got back to the screen.

At least that's how I planned on this working. I'm kinda stuck and not really sure how to debug the message queue. Right now it's throwing an error from

#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;
}

You set the message_queue message queue ID with msgget() , but you then try to send to msgsnd() using the key instead of the message queue ID.

You have the same problem with msgrcv() too.

When I fix those two, I can run the program:

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

I typed abelone apathy on one line, then Control-D to indicate EOF.

As you've got it organized, the writing process fills the message queue before the reading process is enabled. As long as the input isn't too big, that works. However, you probably really want the two processes running concurrently. You'll need to move the wait() calls to give you the concurrency. (Another advantage of properly separating code into functions — it is easier to spot such problems if you hide as much as possible.)

(1) Wrong value to msgsnd/msgrcv . Use thre return value of msgget which is message_queue in your code.

(2) Your fork code is wrong. The parent will create one child then hit wait and wait before the 1st child dies before continuing on to create the 2nd child. You will want to reconsider using exit in some of places you are just using break in your switch statements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM