2014-01-31 147 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()'調用失敗,代碼應該將錯誤報告給標準錯誤並退出或返回。 –