2016-04-24 20 views
1

私は、メインプロセスが「データを作成している」小さなC++プログラムを持っていて、そのデータを読み込む子プロセス(fork)に送ります。私の問題は、学校でコードがうまくいくことですが、自分のラップトップでは、両方のプロセスがプログラムの開始直後に停止してしまいます。具体的には、両方ともWaiting Channel "do_msgrcv"にあります。それは学校で助けている場合、我々はUbuntuの12.04持ちC++ msgsndとmsgrvcがスリープ状態になった

#define VYROBA 1 // Manufacturer 
#define PREPRAVA 2 // Transport 

void manufacturer () { 
    static int count = 0; 
    int rcv [ 2 ]; 

    while (1) { 
     int snd [ 2 ] = { VYROBA, count }; 

     int ret = msgsnd (glb_msg_id, &snd, sizeof (int), 0); 
     ret = msgrcv (glb_msg_id, &rcv, sizeof (int), PREPRAVA, 0); 
     printf ("Got crate\n"); 
    } 
} 

void consumer () { 
    static int count = 0; 
    int rcv [ 2 ]; 

    while (1) { 
     int ret = msgrcv (glb_msg_id, &rcv, sizeof (int), VYROBA, 0); 
     usleep (500000); 
     if (ret < 0) { 
      printf ("Can't read message.\n"); 
     } 

     printf ("Got product: %d\r\n", rcv [ 1 ]); 
     fflush (stdout); 

     rcv [ 1 ]++; 

     if (rcv [ 1 ] == 10) { 
      int snd [ 2 ] = { PREPRAVA, rcv [ 1 ] }; 
      ret = msgsnd (glb_msg_id, &snd, sizeof (int), 0); 
     } else { 
      ret = msgsnd (glb_msg_id, &rcv, sizeof (int), 0); 
     } 
    } 
} 

と私はUbuntuの16.04を使用しています:

は、ここに私のコードです。

ありがとうございました。

+0

送受信の関連コードをこの投稿に直接投稿してください。 patstebinリンクを使用することは悪い習慣と考えられます。なぜなら、誰かがこの質問を6か月で読んでいれば、重要な要素はもう利用できなくなるからです。 – Christophe

+0

@Christopheご迷惑をおかけして申し訳ありませんが、今修正されました。 – cmoud94

+0

あなたのUbuntuの1つが32ビットで、もう1つが64ビットである可能性はありますか? – Christophe

答えて

0

Linuxカーネルsince version 2.6でサポートされているシステムVメッセージキューを使用しているので、両方のUbuntuバージョンを考慮してください。今

手動で見れば、msgrcv() and msgsnd()はhwichが構造を持っている必要があり、メッセージバッファを使用します。

struct msgbuf { 
    long mtype;  /* message type, must be > 0 */ 
    char mtext[1]; /* message data */ 
}; 

はできるだけ早くあなたがこのような構造が、いくつか手動で管理バッファを使用していない始めると、あなたはリスクを持っていますポータブルでないコードを取得する(例えば、エンディアンを考慮して正しいサイズとパディングを確保するなど)。そして、これは確かにここで起こることです。

メッセージ構造体はlongというコードで始まり、int(配列の最初の要素)と同じとみなされます。しかし、C++標準では、intlongのサイズは固定されていません(最小サイズのみ)。このサイズはvary between platforms, compilers and CPU architectureです。例えば:

  • あなたがUbuntuの32ビットを実行して大学であれば、intlongは32ビットであることと同じ大きさを持っているでしょう両方。あなたのコードは動作します。
  • 家庭でUbuntu 64ビットを実行する場合、longは64ビットですが、intは32ビットです。したがって、バッファーが短すぎると、msgsnd()msgrcv()がバッファーをオーバーフローさせます。これは、メッセージ・タイプが壊れているという事実を表すのではなく、未定義の動作です。

私はコードを変更し、バッファの正しい構造を使用すると問題を解決できるはずだと思います。ところで

付記

、あなたのフォーク・ロジックは、製造者()が2回実行されます:元のプロセスに、だけでなく、フォークのもので、消費者が終わったら!より良い

if (!fork ()) { 
    consumer (); 
} 
manufacturer (); 

することになっている場合のみ、それが使われていることを確認するためにelseを使用しています。

+1

ありがとう、私はあなたがここに投稿したものに基づいてカスタム構造体を作成しました。私はまたあなたが提案したように、manufacturer()をelse文で囲みました。 – cmoud94

関連する問題