2017-02-24 36 views
0

嗨我必須開發這個程序,創建4個孩子,並順序,讓他們做一個簡單的操作。第一個將完成總和,第二個完成,第三個複製和第四個分割。父親會在套接字上寫上他希望他的孩子「計算」的兩個數字的字符串,並且每個孩子都應該閱讀這個字符串,提取數字和操作。顯然,作爲兩個管道,需要父親每次寫入字符串,因爲讀取的是孩子。我不明白爲什麼在第二次迭代時,我會收到關於父親寫作的SIGPIPE。有人可以解釋我爲什麼嗎?我調試了3天,但沒有找到任何東西。非常感謝你。SIGPIPE與雙管道雙向消息傳遞

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <errno.h> 
#include <fcntl.h> 

/* 
fd_0 padre escribe y hijo lee ==== padre cierra fd_0[0] y hijo cierra fd_0[1] 
fd_1 hijo escribe y padre lee === padre cierra fd_1[1] y hijo cierra fd_1[0] 
*/ 


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


    char * str = malloc(100*sizeof(char));//hijo 
    char readbuffer_h[150]; 

    char * stringa = malloc(100*sizeof(char));//padre 
    char readbuffer_p[150]; 


    int a,b; 
    int x,y; 
    int n = 4; 
    int i,status,nbytes, pipe_status; 
    int pid, ppid,yo,padre; 
    int fd_0[2], fd_1[2] ; 



    pipe_status=pipe(fd_0); 
    if(pipe_status==- 1) { 
     perror("Error creando la tuberia 0\n"); 
     exit(EXIT_FAILURE); 
    } 


    pipe_status=pipe(fd_1); 
    if(pipe_status== -1) { 
     perror("Error creando la tuberia 1 \n"); 
     exit(EXIT_FAILURE); 
    } 



    for(i=0; i< n; i++){ 

     if ((pid=fork()) <0){ 
     printf("Error al emplear fork\n"); 
     exit(EXIT_FAILURE); 
     } 

/*-------------------------------------------------------------------------------------------------------------------------------------------------*/ 

     else if (pid ==0){// soy el hijo 


      yo = getpid(); 
      padre = getppid(); 
      printf("HIJO: %d, mi padre es: %d\n", yo, padre);  

      close(fd_0[1]); 
      close(fd_1[0]); 

      //TODO 


      nbytes = read(fd_0[0], readbuffer_h, sizeof(readbuffer_h)); 

      sscanf(readbuffer_h, "%d,%d", &x, &y); 


      switch(i) { 

       case 0 : 
        //TODO 
        sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La suma es %d", yo,x,y,(x+y)); 
        break; 

       case 1 : 
        //TODO 
        sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La resta es %d", yo,x,y,(x-y)); 
        break;   

       case 2 : 
        //TODO 
        sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El producto es %d", yo,x,y,(x*y)); 
        break; 

       case 3 : 
        //TODO 
        sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El cociente es %d", yo,x,y,(x/y)); 
        break; 

      } 


      write(fd_1[1], str, strlen(str)); 


      exit(EXIT_SUCCESS); 
     } 

/*-------------------------------------------------------------------------------------------------------------------------------------------------*/ 


     else{ //soy el padre 
      yo = getpid(); 
      printf("PADRE:%d\n", yo); 

      a = 3; b = 4; 

      close(fd_0[0]); 
      close(fd_1[1]); 


      sprintf(stringa,"%d,%d",a,b); 
      printf("Stringa padre : %s\n", stringa); 
       fflush(stdout); 

      write(fd_0[1],stringa,strlen(stringa)); // questa write non va a buon fine 


      wait(&status); 

      read(fd_1[0], readbuffer_p, sizeof(readbuffer_p)); 
      printf("%s\n",readbuffer_p); 
       fflush(stdout); 

     } 


    } 

close(fd_0[0]); 
close(fd_0[1]); 
close(fd_1[0]); 
close(fd_1[1]); 


return 0; 
} 
+0

注意:您提到父級寫入套接字,但您似乎沒有使用任何套接字,只是管道。 –

+0

我相信,英語作爲第二語言,他只是說錯了。 – BaseZen

+0

對不起,我一直在說管道。 (其實英語是我的第三語言,西班牙語第二ahahah) –

回答

1

你讓自己陷入麻煩,試圖使用相同的管道與每個孩子進行交流。

在程序的開頭創建兩個管道。在循環的第一次迭代中,父叉和子繼承所有父節點的打開文件描述符。孩子關閉了不需要的管端,而父母關閉管端不需要。溝通按預期發生(我想) - 迄今爲止一切順利。

但現在考慮循環的第二次迭代。您再次分叉,並且該孩子再次繼承父級的打開文件描述符。但是現在,孩子想要使用的文件描述符在循環的上一次迭代中由父親關閉。我有點驚訝地發現孩子在嘗試使用這些文件描述符時得到EPIPE而不是EBADF,但我並不驚訝它的讀取失敗。

最乾淨的事情是爲每個孩子創建一對新的管道,而不是嘗試重新使用一組管道。如果你想讓它只用一對,那麼父進程必須避免關閉任何管道端(儘管子進程可能會關閉它們的副本,如果你願意的話)。