2010-03-11 124 views
2

这段代码应该是一个整数,创建管道,产生两个孩子,等到他们死了,然后重新开始。但是,在这个循环的第三次左右,我输入了一个号码,并且不再输入我输入的号码。有任何想法吗?为什么fprintf开始乱序打印或根本不打印?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 

#define WRITE 1 
#define READ 0 

int main (int argc, const char * argv[]) { 

    //Pipe file-descriptor array 
    unsigned int isChildA = 0; 
    int pipeA[2]; 
    int pipeB[2]; 
    int num = 0; 

    while(1){ 


    fprintf(stderr,"Enter an integer: "); 
    scanf("%i", &num); 

    if(num == 0){ 
     fprintf(stderr,"You entered zero, exiting...\n"); 
     exit(0); 
    } 

    //Open Pipes 
    if(pipe(pipeA) < 0){ 
     fprintf(stderr,"Could not create pipe A.\n"); 
     exit(1); 
    } 

    if(pipe(pipeB) < 0){ 
     fprintf(stderr,"Could not create pipe B.\n"); 
     exit(1); 
    } 

    fprintf(stderr,"Value read: %i \n", num); 
    fprintf(stderr,"Parent PID: %i\n", getpid()); 

    pid_t procID = fork(); 

    switch (procID) { 
     case -1: 
      fprintf(stderr,"Fork error, quitting...\n"); 
      exit(1); 
      break; 

     case 0: 
      isChildA = 1; 
      break; 

     default: 
      procID = fork(); 

      if (procID<0) { 
       fprintf(stderr,"Fork error, quitting...\n"); 
       exit(1); 
      } 
      else if(procID == 0){ 
       isChildA = 0; 
      } 

      else { 

       write(pipeA[WRITE], &num, sizeof(int)); 
       close(pipeA[WRITE]); 
       close(pipeA[READ]); 
       close(pipeB[WRITE]); 
       close(pipeB[READ]); 

       pid_t pid; 

       while (pid = waitpid(-1, NULL, 0)) { 
        if (errno == ECHILD) { 
         break; 
        } 
       } 

      } 


      break; 
    } 

    if (procID == 0) { 
     //We're a child, do kid-stuff. 
     ssize_t bytesRead = 0; 
     int response; 

     while (1) { 

      while (bytesRead == 0) { 
       bytesRead = read((isChildA?pipeA[READ]:pipeB[READ]), &response, sizeof(int)); 
      } 
      if (response < 2) { 
       //Kill other child and self 
       fprintf(stderr, "Terminating PROCID: %i\n", getpid()); 
       write((isChildA?pipeB[WRITE]:pipeA[WRITE]), &response, sizeof(int)); 
       close(pipeA[WRITE]); 
       close(pipeA[READ]); 
       close(pipeB[WRITE]); 
       close(pipeB[READ]); 
       return 0; 
      } 
      else if(!(response%2)){ 
       //Even 
       response/=2; 
       fprintf(stderr,"PROCID: %i, VALUE: %i\n", getpid(), response); 
       write((isChildA?pipeB[WRITE]:pipeA[WRITE]), &response, sizeof(int)); 
       bytesRead = 0; 
      } 

      else { 
       //Odd 
       response*=3; 
       response++; 
       fprintf(stderr,"PROCID: %i, VALUE: %i\n", getpid(), response); 
       write((isChildA?pipeB[WRITE]:pipeA[WRITE]), &response, sizeof(int)); 
       bytesRead = 0; 
      } 


     } 
    } 
} 

    return 0; 
} 

这是我得到的输出...

bash-3.00$ ./proj2 
Enter an integer: 101 
Value read: 101 
Parent PID: 9379 
PROCID: 9380, VALUE: 304 
PROCID: 9381, VALUE: 152 
PROCID: 9380, VALUE: 76 
PROCID: 9381, VALUE: 38 
PROCID: 9380, VALUE: 19 
PROCID: 9381, VALUE: 58 
PROCID: 9380, VALUE: 29 
PROCID: 9381, VALUE: 88 
PROCID: 9380, VALUE: 44 
PROCID: 9381, VALUE: 22 
PROCID: 9380, VALUE: 11 
PROCID: 9381, VALUE: 34 
PROCID: 9380, VALUE: 17 
PROCID: 9381, VALUE: 52 
PROCID: 9380, VALUE: 26 
PROCID: 9381, VALUE: 13 
PROCID: 9380, VALUE: 40 
PROCID: 9381, VALUE: 20 
PROCID: 9380, VALUE: 10 
PROCID: 9381, VALUE: 5 
PROCID: 9380, VALUE: 16 
PROCID: 9381, VALUE: 8 
PROCID: 9380, VALUE: 4 
PROCID: 9381, VALUE: 2 
PROCID: 9380, VALUE: 1 
Terminating PROCID: 9381 
Terminating PROCID: 9380 
Enter an integer: 102 
Value read: 102 
Parent PID: 9379 
PROCID: 9386, VALUE: 51 
PROCID: 9387, VALUE: 154 
PROCID: 9386, VALUE: 77 
PROCID: 9387, VALUE: 232 
PROCID: 9386, VALUE: 116 
PROCID: 9387, VALUE: 58 
PROCID: 9386, VALUE: 29 
PROCID: 9387, VALUE: 88 
PROCID: 9386, VALUE: 44 
PROCID: 9387, VALUE: 22 
PROCID: 9386, VALUE: 11 
PROCID: 9387, VALUE: 34 
PROCID: 9386, VALUE: 17 
PROCID: 9387, VALUE: 52 
PROCID: 9386, VALUE: 26 
PROCID: 9387, VALUE: 13 
PROCID: 9386, VALUE: 40 
PROCID: 9387, VALUE: 20 
PROCID: 9386, VALUE: 10 
PROCID: 9387, VALUE: 5 
PROCID: 9386, VALUE: 16 
PROCID: 9387, VALUE: 8 
PROCID: 9386, VALUE: 4 
PROCID: 9387, VALUE: 2 
PROCID: 9386, VALUE: 1 
Terminating PROCID: 9387 
Terminating PROCID: 9386 
Enter an integer: 104 
Value read: 104 
Parent PID: 9379 
Enter an integer: PROCID: 9388, VALUE: 52 
PROCID: 9389, VALUE: 26 
PROCID: 9388, VALUE: 13 
PROCID: 9389, VALUE: 40 
PROCID: 9388, VALUE: 20 
PROCID: 9389, VALUE: 10 
PROCID: 9388, VALUE: 5 
PROCID: 9389, VALUE: 16 
PROCID: 9388, VALUE: 8 
PROCID: 9389, VALUE: 4 
PROCID: 9388, VALUE: 2 
PROCID: 9389, VALUE: 1 
Terminating PROCID: 9388 
Terminating PROCID: 9389 
105 
Value read: 105 
Parent PID: 9379 
Enter an integer: PROCID: 9395, VALUE: 316 
PROCID: 9396, VALUE: 158 
PROCID: 9395, VALUE: 79 
PROCID: 9396, VALUE: 238 
PROCID: 9395, VALUE: 119 
PROCID: 9396, VALUE: 358 
PROCID: 9395, VALUE: 179 
PROCID: 9396, VALUE: 538 
PROCID: 9395, VALUE: 269 
PROCID: 9396, VALUE: 808 
PROCID: 9395, VALUE: 404 
PROCID: 9396, VALUE: 202 
PROCID: 9395, VALUE: 101 
PROCID: 9396, VALUE: 304 
PROCID: 9395, VALUE: 152 
PROCID: 9396, VALUE: 76 
PROCID: 9395, VALUE: 38 
PROCID: 9396, VALUE: 19 
PROCID: 9395, VALUE: 58 
PROCID: 9396, VALUE: 29 
PROCID: 9395, VALUE: 88 
PROCID: 9396, VALUE: 44 
PROCID: 9395, VALUE: 22 
PROCID: 9396, VALUE: 11 
PROCID: 9395, VALUE: 34 
PROCID: 9396, VALUE: 17 
PROCID: 9395, VALUE: 52 
PROCID: 9396, VALUE: 26 
PROCID: 9395, VALUE: 13 
PROCID: 9396, VALUE: 40 
PROCID: 9395, VALUE: 20 
PROCID: 9396, VALUE: 10 
PROCID: 9395, VALUE: 5 
PROCID: 9396, VALUE: 16 
PROCID: 9395, VALUE: 8 
PROCID: 9396, VALUE: 4 
PROCID: 9395, VALUE: 2 
PROCID: 9396, VALUE: 1 
Terminating PROCID: 9395 
Terminating PROCID: 9396 
105 
Value read: 105 
Parent PID: 9379 
Enter an integer: PROCID: 9397, VALUE: 316 
PROCID: 9398, VALUE: 158 
PROCID: 9397, VALUE: 79 
PROCID: 9398, VALUE: 238 
PROCID: 9397, VALUE: 119 
PROCID: 9398, VALUE: 358 
PROCID: 9397, VALUE: 179 
PROCID: 9398, VALUE: 538 
PROCID: 9397, VALUE: 269 
PROCID: 9398, VALUE: 808 
PROCID: 9397, VALUE: 404 
PROCID: 9398, VALUE: 202 
PROCID: 9397, VALUE: 101 
PROCID: 9398, VALUE: 304 
PROCID: 9397, VALUE: 152 
PROCID: 9398, VALUE: 76 
PROCID: 9397, VALUE: 38 
PROCID: 9398, VALUE: 19 
PROCID: 9397, VALUE: 58 
PROCID: 9398, VALUE: 29 
PROCID: 9397, VALUE: 88 
PROCID: 9398, VALUE: 44 
PROCID: 9397, VALUE: 22 
PROCID: 9398, VALUE: 11 
PROCID: 9397, VALUE: 34 
PROCID: 9398, VALUE: 17 
PROCID: 9397, VALUE: 52 
PROCID: 9398, VALUE: 26 
PROCID: 9397, VALUE: 13 
PROCID: 9398, VALUE: 40 
PROCID: 9397, VALUE: 20 
PROCID: 9398, VALUE: 10 
PROCID: 9397, VALUE: 5 
PROCID: 9398, VALUE: 16 
PROCID: 9397, VALUE: 8 
PROCID: 9398, VALUE: 4 
PROCID: 9397, VALUE: 2 
PROCID: 9398, VALUE: 1 
Terminating PROCID: 9397 
Terminating PROCID: 9398 
106 
Value read: 106 
Parent PID: 9379 
Enter an integer: PROCID: 9399, VALUE: 53 
PROCID: 9400, VALUE: 160 
PROCID: 9399, VALUE: 80 
PROCID: 9400, VALUE: 40 
PROCID: 9399, VALUE: 20 
PROCID: 9400, VALUE: 10 
PROCID: 9399, VALUE: 5 
PROCID: 9400, VALUE: 16 
PROCID: 9399, VALUE: 8 
PROCID: 9400, VALUE: 4 
PROCID: 9399, VALUE: 2 
PROCID: 9400, VALUE: 1 
Terminating PROCID: 9399 
Terminating PROCID: 9400 
^C 

另一件事,很奇怪,当跑在Xcode中也可以正常工作。但是,当从Solaris或OSX上的bash运行时,它会起作用。

回答

2

更换你waitpid()并尝试这个:

/* 
while (pid = waitpid(-1, NULL, 0)) 
{ 
    if (errno == ECHILD) 
    { 
     break; 
    } 
} 
*/ 

while (1) 
{ 
    if ((pid = waitpid(-1, NULL, 0)) == -1) 
    { 
     if (errno == ECHILD) 
      break; 
    } 
    else 
     printf("I am %d and I am reaped %d\n", getpid(), pid); 
} 
+0

谢谢!这工作!但是,你能解释一下你的解决方案和我的解决方案有什么不同吗? –

+0

waitpid()在成功时不会重置errno,因此在第一个ECHILD之后,错误代码仍保留在原位。在下一次迭代中,即使waitpid()发现一个孩子,该循环在ECHILD测试中退出,并且不会捕获第二个孩子。这搞砸了打印序列。 – Duck

0

在打印字符串的末尾没有换行符时,在fprintf后调用fflush。

+0

感谢您的回答,但我已经试过了。这是我的理解,stderr不像标准输出缓冲,因此不需要fflush。 –

+0

这是正确的,stderr没有被缓冲。 – tomlogic