2014-01-31 107 views
0

我有一段代码,我试图改变。代码只是两个管道,它们在两个进程(父进程和子进程)之间进行通信。我正在尝试创建程序的“干净终止”,以便无论何时从父级发送0到子级,相应的进程都会关闭所有管道的末端。如何正确关闭管道

的代码是一样的东西:

int main 
{ 
    int pipe1[2], pipe2[2], value, request; 
    if(pipe(pipe1) < 0 || pipe(pipe2) < 0) 
     printf("Failed to create pipes.\n"); 

    switch(fork()) 
    { 
     case -1: 
      perror("Cannot create fork.\n"); 
      break; 

     case 0: 
      close (pipe1[WRITE]); 
      close (pipe2[READ]); 
      close (0); 
      close (1); 

     for(;;) { 
      read(pipe1[READ], &value, sizeof value); 

      //If user enters 0. 
      if(value == 0) 
      { 
       printf("Terminating child process!\n"); 
       close(pipe1[READ]); 
       //write a 0 back to the parent so that it can close its end. 
       write(pipe2[WRITE], 0, sizeof (int)); 
       close(pipe2[WRITE]); 
       exit(0); 
      } 
      else 
      { 
       /*Enter function to do something on the number here*/ 
       write(pipe2[WRITE], &result, sizeof result); 
      } 
     } 
     break; 

     default: /* PARENT PROCESS - PRODUCER */ 
      close(pipe1[READ]); 
      close(pipe2[WRITE]); 
      for(;;) { 
       printf("Ange ett tal: "); 
       scanf("%d", &value); 
       if(write(pipe1[WRITE], &value, sizeof value) != sizeof value) 
       { 
        perror("Cannot write thru pipe.\n"); 
        return 1; 
       } 

      //Clean shutdown if value == 0 
       if(value == 0) 
      { 
       close(pipe2[WRITE]); 
       read(pipe2[READ],&result,sizeof(result)); 
       if(result == 0) 
       { 
        close(pipe2[READ]); 
        printf("Pipe2[Read] closed!\n"); 
        wait(0); 
       } 
      } 

      else 
      { 
       read(pipe2[READ],&result,sizeof(result)); 
       printf("Result: %d.\n",result); 
      } 

    } 
    break; 
    } 


} 

我一直在这几个小时了,我不明白为什么我的代码行事都疯了。当我进入1它说:“管关闭,如果我进入0它试图给人一种错误Cannot create pipes!之前接受其他输入。

我想我失去了一些东西很基本的在这里。关于这个问题的任何帮助是非常赞赏。

+2

你在哪里创建管?你'if'语句检查的内容管的值,但你永远不叫'管()'。 – Barmar

+2

,应该管总是一个2元素的数组,为什么你有'int pipe1 [1]'? – Barmar

+0

还...返回代码是你的朋友 - 使用它们。 – Duck

回答

0

注意关键的变化!

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

enum { READ = 0, WRITE = 1 }; 

int main(void) 
{ 
    int pipe1[2], pipe2[2], value, result; 
    if (pipe(pipe1) < 0 || pipe(pipe2) < 0) 
     printf("Failed to create pipes.\n"); 

    switch (fork()) 
    { 
    case -1: 
     perror("Cannot create fork.\n"); 
     break; 

    case 0: 
     close(pipe1[WRITE]); 
     close(pipe2[READ]); 

     while (read(pipe1[READ], &value, sizeof(value)) > 0) 
     { 
      // If user enters 0. 
      if (value == 0) 
      { 
       printf("Terminating child process!\n"); 
       close(pipe1[READ]); 
       // write a 0 back to the parent so that it can close its end. 
       write(pipe2[WRITE], 0, sizeof(int)); 
       close(pipe2[WRITE]); 
       exit(0); 
      } 
      else 
      { 
       result = value + 1; 
       write(pipe2[WRITE], &result, sizeof result); 
      } 
     } 
     break; 

    default:  /* PARENT PROCESS - PRODUCER */ 
     close(pipe1[READ]); 
     close(pipe2[WRITE]); 
     for (; ;) 
     { 
      printf("Ange ett tal: "); 
      if (scanf("%d", &value) != 1) 
       break; 
      if (write(pipe1[WRITE], &value, sizeof(value)) != sizeof(value)) 
      { 
       perror("Cannot write thru pipe.\n"); 
       return 1; 
      } 
      // Clean shutdown if value == 0 
      if (value == 0) 
      { 
       close(pipe1[WRITE]); // Key change! 
       if (read(pipe2[READ], &result, sizeof(result)) <= 0 || result == 0) 
       { 
        close(pipe2[READ]); 
        printf("Pipe2[Read] closed!\n"); 
        wait(0); 
        break; 
       } 
      } 
      else 
      { 
       if (read(pipe2[READ], &result, sizeof(result)) <= 0) 
        break; 
       printf("Result: %d.\n", result); 
       if (result == 0) 
       { 
        printf("Read zero - exit\n"); 
        close(pipe1[WRITE]); 
        close(pipe2[READ]); 
        break; 
       } 
      } 
     } 
     break; 
    } 

    return 0; 
} 
+0

谢谢Jonathan,解决方案确实解决了问题。不过,我想了解一切,所以我会问一些后续问题。首先你做了一个条件:if(读取(pipe2 [READ],&result,sizeof(result))<= 0 || result == 0)'读取文件描述符并在同一语句中检查结果是'0'。然后在右边的'else'语句中有另一个'if(result == 0)。那是什么目的? –

+0

请务必检查您的阅读操作。可以说,测试应该是'if(read(pipe2 [READ],&result,sizeof(result))!= sizeof(result)|| result == 0)',但是我写的是相当安全的。它检查读取是否有效,以及读取是否有效,结果是否为零。我相信这两个都是终止的理由。用'result = value + 1;''function',如果你输入-1,则代码退出;如果您键入0,代码将退出;否则,代码继续。对'scanf()'的检查至关重要;如果您键入'a'而不是数字,并且不测试'scanf()',您的程序将运行很长时间。等 –

+0

顺便说一下,如果'pipe()'调用失败,代码应该将错误报告给标准错误并退出或返回。 –