2016-05-04 6 views
0

私はfork()を使ってメッセージキューを実装しようとしています。ここに私が持っているものがあります。fork()の使い方が間違っていますか?

#define DATA_SIZE 256 
#define BUFF_SIZE 4096 

int main(void) { 
    // seed the random number generator 
    srand(time(NULL)); 

    // Parent and Ground Truth Buffers 
    char ground_truth[BUFF_SIZE] = {0}; // used to verify 
    char producer_buffer[BUFF_SIZE] = {0}; // used by the parent 
    int i = 0; 
    int msqid = 0; 
    int rc; 
    pid_t msq_pid; 

    for (i = 0; i < BUFF_SIZE; ++i) { 
     producer_buffer[i] = ground_truth[i] = rand() % 256; 
    } 

    const key_t s_msq_key = 1337; // used to create message queue ipc 
    const char *const p_msq_key = "/OS_MSG"; 

    msqid = msgget(s_msq_key, IPC_CREAT | 0660); 

    msq_pid = fork(); 

    if(msq_pid == -1){ 
     perror("error forking"); 
     exit(1); 
    } 

    if(msq_pid > 0){ 
     rc = msgsnd(msqid, (void*)p_msq_key, sizeof(producer_buffer), 0); 
     printf("MESSAGE SENT\n"); 
     if(rc < 0){ 
      perror("message send failed"); 
      exit(1); 
     } 
     return 1; 
    } else { 
     if(memcmp(producer_buffer, ground_truth, DATA_SIZE) == 0){ 
      printf("MESSAGE REC"); 
      return 1; 
     } 
     exit(1); 
    } 

return 0; 
} 

私の実際の問題が追加されました。うまくいけば、これはあまりあまりありません。これは宿題ですが、コードの助けを求めるだけではありません。もう一度、私は取得しています唯一の結果がMESSAGE RECはなくMESSAGE REC

EDIT続いMESSAGE SENTです:

さて、私はmsq_pid == -1のためのエラーチェックを追加しました。また、仮想マシンを再起動すると、MESSAGE SENTMESSAGE RECの両方を取得できたことに気付きました。プログラムをさらにいくつか実行した後、私はMESSAGE RECを受信し始めました。誰かがこれを説明できますか?

+2

私たちが問題を示すコンパイルできる短いプログラム全体を投稿してください。 –

+2

そのコードが 'main'にある場合、それはうまくいくはずです(最初の' printf'の終わりに '\ n'を付けるべきです)。サブルーチンに移動した場合は、十分なコードが表示されていません。 – user3386109

+0

私はすべての論理を含むように問題を編集しました。 –

答えて

2

fork()マニュアルページには、あなたの子供と親が逆転していることが問題であるようです。 fork()は子プロセスに0を返します。親に> 0を返し、エラーが発生すると-1を返します。だからあなたのコードでは、あなたは持っている必要があります。

if(msg_pqid == 0) { 
    /* The child sends the message */ 
} else { 
    /* Parent receives the message */ 
} 

を、私はそうのようなスイッチを使用することを好む:

switch ((msg_pqid = fork())) { 
case -1: 
    /* Error */ 
case 0: 
    /* Child sends message */ 
default: 
    /* Parent receives message */ 
} 
+0

は問題の原因ではありません。子が 'msgrcv()'を呼び出すことができず、msgget()とmsgsnd()のいくつかのパラメータが正しくありません。 – user3629249

+0

問題の根本ではありません。しかし、これは宿題の問題であると述べています。私は、フォーク()の使用に疑問を抱くことにしました。不確実性がなくなり、自分自身で問題の根本を見つけることに専念できるようになりました。 – xmonk

0

システムコール不正に使用されているいくつかの。

システムコールのいくつかから返されるステータスは、以下のコード

を無視されている:

  1. がきれい
  2. をコンパイルし、所望の動作
  3. は、すべてのエラー条件
を処理実行現在
#include <stdio.h> 
#include <stdlib.h> 

#include <time.h> //time() 

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/msg.h> 

#include <unistd.h> //fork() 

#include <string.h> //memcmp() 


#define MAX_MSG_LEN (10) 
#define ACT_MSG_LEN (8) 

// Parent and Ground Truth Buffers 
struct msgbuf 
{ 
    long mtype;  /* message type, must be > 0 */ 
    char mtext[ MAX_MSG_LEN ]; /* message data */ 
}; 

struct msgbuf ground_truth; // used to verify 
struct msgbuf producer_buffer = {1,"message"}; // used by the parent 

int main(void) 
{ 
    // seed the random number generator 
    srand((unsigned)time(NULL)); 



    //int i = 0; 
    int msqid = 0; 
    int rc; 
    pid_t msq_pid; 
    ssize_t rcvStatus; 

    const key_t s_msq_key = 1337; // used to create message queue ipc 
    //const char *const p_msq_key = "/OS_MSG"; 

    msqid = msgget(s_msq_key, IPC_CREAT | 0660); 
    if(-1 == msqid) 
    {// then msgget failed 
     perror("msgget failed"); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, msgget successful 

    msq_pid = fork(); 

    while(1) 
    { 
     switch(msq_pid) 
     { 
      case -1: 
       perror("error forking"); 
       exit(EXIT_FAILURE); 
       break; 

      default: // parent process 
       rc = msgsnd(msqid, &producer_buffer, sizeof producer_buffer, 0); 
       printf("MESSAGE SENT: %s\n", producer_buffer.mtext); 
       if(rc < 0) 
       { 
        perror("message send failed"); 
        exit(EXIT_FAILURE); 
       } 
       break; 

      case 0: // child process 
       rcvStatus = msgrcv(msqid, &ground_truth, sizeof(ground_truth), 0, 0); 
       if(-1 == rcvStatus) 
       { // then msgrcv failed 
        perror("msgrcv failed"); 
        exit(EXIT_FAILURE); 
       } 

       // implied else, msgrcv successful 

       if(memcmp(producer_buffer.mtext, ground_truth.mtext, ACT_MSG_LEN) == 0) 
       { 
        printf("MESSAGE REC %s\n", ground_truth.mtext); 
       } 

       else 
       { 
        printf("msg Sent: '%s' does not match msg Recv: '%s'\n", producer_buffer.mtext, ground_truth.mtext); 
       } 
       break; 
     } // end switch 
    } // end while forever 
} // end function: main