2016-04-24 51 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