簡體   English   中英

兩個派生進程之間的消息隊列導致msgsnd的參數無效

[英]Message queue between two forked processes causing invalid argument from msgsnd

該程序將創建兩個子進程。 第一個子進程(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;
}

您可以使用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並等待第一個孩子去世,然后繼續創建第二個孩子。 您可能想在switch語句中剛剛使用break某些地方重新考慮使用exit

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM