2016-04-24 78 views
0

我有以下任務要做:Unix進程PIPE

乒乓。兩個進程將玩乒乓球遊戲。 第一個進程將生成一個5000到15000之間的隨機數,並將其發送到另一個進程。 此過程將減去一個隨機值(介於50和1000之間)並將發回數字, 這些過程之間的聊天將使用管道來實現。 遊戲在值低於零時結束。 每個進程將打印收到的值。

所以我寫了下面的代碼:

#include <stdio.h> 
#include <time.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 

int main() 
{ 
    int p[2]; 
    int a, n; 

    pipe(p); 
    int pid = fork(); 
    if (pid == 0) 
    { 
     int r = 0; 
     srand(time(NULL)); 
     while (r < 50 || r > 1000) 
     { 
      r = rand(); 
     } 

     if ((a=read(p[0], &n, sizeof(int)))==-1) 
      perror("Error read pipe:"); 

     printf("Process 2 recived %d\n", a); 
     a = a - r; 

     close(p[0]); close(p[1]); 
    } 
    else if (pid > 0) 
    { 
     srand(time(NULL)); 
     while (n < 5000 || n > 15000) { 
      n = rand(); 
     } 

     while (n > 0) 
     { 
      printf("Process 1 recived %d\n", n); 
      if (write(p[1], &n, sizeof(int))==-1) 
       perror("Error write pipe:"); 

      wait(0); 
     } 
    } 
    return 0; 
} 

當執行它會在一個無限循環,其打印"Process 1 received 4",我不知道爲什麼。

我創造了另一個管道,現在它正確打印第一個接收值,但在第二過程中它會發生同樣的事情

Process 1 recived 9083 
Process 2 recived 4 
Process 1 recived 4 
and infinite loop 
+0

請不要在你的問題的更新代碼。 – jdarthenay

+0

請注意,兩個隨機數序列實際上保證是相同的(如果其中一個進程在T時刻執行'time(NULL)',另一個進程在時間T + 1執行,它們只會有所不同大多數他們都會在時間T執行它)。一個簡單的解決方法是使用'time(NULL)+ pid'來代替'time(NULL)'。 –

回答

1

我給你糾正程序與評論的解釋:

#include <stdio.h> 
#include <time.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 

int main() 
{ 
    int p[2]; 
    int p2[2]; 
    int a, n; 

    pipe(p); 
    pipe(p2); 
    int pid = fork(); 
    if (pid == 0) 
    { 
     close(p[1]); // not writing in p, so closing p[1] immediately 
     close(p2[0]); // not reading in p2, so closing p2[0] immediately 

     srand(time(NULL)); 

     do { 
      if ((a = read(p[0], &n, sizeof(int)))==-1) 
       perror("Error read pipe:"); 

      if (a == 0) // nothing read means all processes have closed p[1] 
       n = 0; 
      else 
       printf("Process 2 recived %d\n", n); 

      int r = 50 + rand() % 950; // Only need one random number, and need one different each time 
      n -= r; 
      if (n > 0) 
      { 
       if(write(p2[1], &n, sizeof(int))==-1) 
        perror("Error write pipe:"); 
      } 
     } while (n > 0); 

     close(p[0]); close(p2[1]); 
     exit(0); // or return(0) - as pointed out by Stian 
    } 
    else if (pid > 0) 
    { 
     close(p[0]); // not reading in p, so closing p[0] immediately 
     close(p2[1]); // not writing in p2, so closing p2[1] immediately 

     srand(time(NULL) + pid); // Adding pid so that processes each use a different seed 
     n = rand() % 10000 + 5000; // Only need one random number 

     while (n > 0) 
     { 
      if (write(p[1], &n, sizeof(int))==-1) 
       perror("Error write pipe:"); 

      // wait(0); Wrong use of wait() 
      if ((a = read(p2[0], &n, sizeof(int)))==-1) 
       perror("Error read pipe:"); 

      if (a == 0) // nothing read means all processes have closed p2[1] 
       n = 0; 
      else 
       printf("Process 1 recived %d\n", n); 

      int r = 50 + rand() % 950; 
      n -= r; 
     } 

     close(p[1]); close(p2[0]); 
    } 

    wait(NULL); // Better use of wait(). Still not perfect, you need to check return value. 
    return 0; 
} 
+0

孩子應該在完成時調用_exit,否則將會等待 –

+0

@StianSkjelstad:由於孩子沒有自己的孩子,所以wait()會立即返回「-1」和「errno == EAGAIN」,這除了可以避免的(無害的)系統調用之外,這不是一個問題。 –

+0

@JonathanLeffler事實上,不是一個錯誤,只是一個不必要的電話,我不喜歡他們... – jdarthenay

0

需要兩個管道。每個方向一個

+0

像孩子的管道和父親的管道? – Papanash

+0

管道是單向數據流。一個管道應由父母書寫,由孩子閱讀,第二個管道反向 –

+0

我做了另一個管道,我仍然有一個無限循環,你可以看看編輯? – Papanash