2015-12-08 108 views
1

我有以下代碼。它由一個父進程和兩個子進程(一個生產者和一個消費者)組成。生產者接受用戶輸入並將其傳遞給消費者,消費者總結已經發生的元音總數。父進程只監聽兩個子進程,並在出於任何原因停止時重新啓動它們。生產者進程在用戶輸入'p'時退出,當消費者進程收到包含'y'的字符串時停止。正在退出子進程

我遇到的問題是生產者進程中的_exit()函數調用不會導致進程終止。消費者過程中的_exit()函數調用按預期工作。爲什麼生產者函數不能正確終止消費者進程?

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <signal.h> 

int main(){ 
    pid_t c_p, c_c; 
    int p[2]; 
    pipe(p); 
    c_p = fork(); 
    if(c_p > 0) c_c = fork(); 

    for(;;){ 
     // Producer Process 
     if(c_p == 0){ 
      char c[20]; 
      printf("%s", "Enter a string: \n"); 
      fgets(c, 20, stdin); 
      if(c[0] == 'p' && strlen(c) == 2) _exit(1); 
      close(p[0]); 
      write(p[1], c, (strlen(c) + 1)); 
     } 

     // Consumer Process 
     else if(c_c == 0){ 
      int j; 
      static int a = 0, e = 0, i = 0, o = 0, u = 0; 
      char buffer[20]; 
      close(p[1]); 
      read(p[0], buffer, sizeof(buffer)); 

      for(j = 0; j < strlen(buffer); j++){ 
       if  (buffer[j] == 'a' || buffer[j] == 'A') a++; 
       else if(buffer[j] == 'e' || buffer[j] == 'E') e++; 
       else if(buffer[j] == 'i' || buffer[j] == 'I') i++; 
       else if(buffer[j] == 'o' || buffer[j] == 'O') o++; 
       else if(buffer[j] == 'u' || buffer[j] == 'U') u++; 
       else if(buffer[j] == 'y' || buffer[j] == 'Y') _exit(1); 
      } 

      printf("Sum of Vowels... \tA: %d \tE: %d \tI: %d \tO: %d \tU: %d\n", a, e, i, o, u); 
     } 

     // Main Process 
     else{ 
      int status; 
      pid_t result = waitpid(c_c, &status, WNOHANG); 
      if(result > 0){ 
       c_c = fork(); 
      } 

      /*result = waitpid(c_p, &status, WNOHANG); 
      if(result > 0){ 
       c_p = fork(); 
      }*/ 
     } 
    } 

    return 0; 
} 

回答

5

有四個過程存在於你的程序後,

c_p = fork(); c_c = fork();

你可以把它改成這樣:

c_p = fork(); 
if (c_p > 0) 
{ 
    c_c = fork(); 
    // Do something. 
} else if (c_p == 0) 
{ 
    // Do something. 
} 
+0

優秀。差不多了。該過程現在終止正確,但不斷要求用戶輸入。有什麼方法可以讓程序停止調用printf()?我會假設在處理程序被殺之後它會停止... – mstagg

+1

好的,問題在於,waitpid將返回其狀態已更改的子進程標識的pid。無論消費者遇到什麼樣的投入,似乎你總是會分享一個新的消費者流程。如果要通過輸入'y/Y'來終止消費者,請將if(result> 0)更改爲if(status == 0) –