2015-12-08 107 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) –