2016-02-09 46 views
0

我正在研究一个程序,该程序将接收一个整数并创建两个进程,一个父进程和一个子进程。父母会从整数中减去5,将其传递给将要除以5的孩子,然后他们将重复该过程5次,每次打印整数的当前值。Linux系统使用Fork()将子字段传递给子进程和父进程调用问题

该整数可以通过文本文件传递并且可以被写入和读取,或者可以使用管道更简单。

我一直在查找所需的系统调用,并有一个半工作程序。然而,我一直坚持了几个小时,我认为我的问题是我无法让他们等待对方完成,因为我的输出不正确。

这是我到目前为止。

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

int main(void) 
{  
    int x=19530; 
    int w=1; 
    int fd[2]; 
    pipe(fd); 
    int pid = fork(); 

    int k; 
    for (k=0; k<5; k++) { 
     if (pid>0) { 
      //int x = 19530; 

      if ((close(fd[0]))==-1) { 
       perror("Close:"); 
      } 

      read(fd[0], &x, sizeof(int)); 
      x=x-5; 
      write (fd[1], &x, sizeof(int)); 
      printf("X in parent %d\n", x); 

      close(fd[1]); 
      close(fd[0]); 
     } else if (pid==0) { 

      if ((close(fd[1]))==-1) { 
       perror("Close:"); 
      } 

      read(fd[0], &x, sizeof(int)); 
      x=x/5; 
      printf("X in child %d\n", x); 
      write (fd[1], &x, sizeof(int)); 

      close(fd[1]); 
      close(fd[0]); 
     } 
    } 
    return 0; 
} 

但是我的输出是一个问题,我得到:

X in parent 19525 
X in child 3905 
Close:: Bad file descriptor 
X in parent 19520 
Close:: Bad file descriptor 
X in parent 19515 
Close:: Bad file descriptor 
X in parent 19510 
Close:: Bad file descriptor 
X in parent 19505 
Close:: Bad file descriptor 
X in child 781 
Close:: Bad file descriptor 
X in child 156 
Close:: Bad file descriptor 
X in child 31 
Close:: Bad file descriptor 
X in child 6 

它似乎开始很好,但随后则父运行次数过多,孩子没有传回正确在孩子赶上之前一排。我也一直试图修复那个不好的文件描述符,但无济于事。

任何帮助将不胜感激。

谢谢。

+2

关闭它后,您既不能读取也不能写入文件描述符。 – alvits

+4

您创建了一对文件描述符。然后,你关闭他们5次。第一次关闭它后,它关闭。你期望发生什么? – immibis

+2

你有每一方首先执行'read',然后执行'write'。一个'read'将会阻塞,直到有人调用'write',那么谁先写? – dbush

回答

2
#include <stdio.h> 
#include <unistd.h> 
#include <err.h> 

#define ok(x) ({ int i_ = (x); if (i_ == -1) err(1, #x); i_; }) 

enum { p_, c_ }; // parent, child 
enum { r_, w_ }; // read, write 

int main(void) 
{ 
     int x = 19530; 
     int fd[2][2]; 
     int pid; 

     ok(pipe(fd[0])); 
     ok(pipe(fd[1])); 

     ok(pid = fork()); 

     close(fd[p_][pid ? r_ : w_]); 
     close(fd[c_][pid ? w_ : r_]); 

     for (int i = 0; i < 5; i++) { 
       if (pid) { 
         x -= 5; 
         printf("X in parent %d\n", x); 
         ok(write(fd[p_][w_], &x, sizeof(x))); 
         ok(read(fd[c_][r_], &x, sizeof(x))); 
       } 
       else { 
         ok(read(fd[p_][r_], &x, sizeof(x))); 
         x /= 5; 
         printf("X in child %d\n", x); 
         ok(write(fd[c_][w_], &x, sizeof(x))); 
       } 
     } 
     return 0; 
} 

管道是单向的,所以你需要两个。我使用了一些枚举来尝试使事情更易于阅读。

+0

您正在使用GCC扩展(['语句表达式'](https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/Statement-Exprs.html#Statement-Exprs)),而无需调用出。使用''很有趣;它可以在BSD(包括Mac OS X)和Linux上使用,但不一定在其他地方使用。 OTOH,它非常符合我在过去25年左右一直使用的一套错误报告程序。就我个人而言,我发现单个字母的尾部下划线名称让人分心。 –

+0

如果有人需要它,在CCAN上有一个err.h的开源实现:http://ccodearchive.net/info/err.html。语句表达式由gcc,clang,甚至icc支持 - 所以我感觉很好。 :) – dancancode

相关问题