2016-04-24 44 views
1

我有一個小型的C++程序,其中主進程是「創建數據」並將它們發送到應讀取數據的子進程。我的問題是,在學校我的代碼運行良好,但在我自己的筆記本電腦上,這兩個進程在程序啓動後就卡住了。具體來說,他們都在等待頻道「do_msgrcv」。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 12.04,我使用Ubuntu 16.04。

感謝您的任何幫助。

+0

請您在這篇文章中直接發送發送/接收的相關代碼?使用patstebin鏈接被認爲是不好的做法,因爲如果有人在6個月內閱讀這個問題,關鍵元素將不再可用。 – Christophe

+0

@Christophe對不便,現在已修好。 – cmoud94

+0

是否有可能你的Ubuntu是32位而其他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()過沖緩衝區。這將是未定義的行爲,而不是說消息類型會被破壞。

我認爲改變你的代碼並使用正確的緩衝區結構應該可以解決這個問題。

附記

順便說一句,你的分叉邏輯使得製造商()執行兩次:在原有的工藝,同時也對那些分叉一次消費完!

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

更好地使用else以確保它僅用於應該使用的位置。

+1

非常感謝你,我已經根據你在這裏發佈的結構創建了自定義結構,並且它工作正常。按照您的建議,我還附上了製造商()和其他語句。 – cmoud94