2017-02-24 12 views
0

こんにちは私は4人の子供を作り、逐次、簡単な操作を行うこのプログラムを開発しなければなりません。最初は合計を行い、残りの2つ目は乗算を行い、3つ目は乗算を行い、4つ目は除算を行います。父親は、子供が "計算する"ことを望む2つの数字の文字列をソケットに書き、すべての子供はこの文字列を読み、数字を抽出し、操作にすべきです。明らかに、2つのパイプであることは、子供が読むために、父親が毎回文字列を書く必要があります。私は2回目の反復でなぜ父親の書き込みにSIGPIPEを受け取るのか理解できません。誰かがなぜ私を説明することはできますか?私はデバッグで3日を過ごしましたが、何も見つかりませんでした。どうもありがとうございました。2つのパイプを使った双方向メッセージングの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

申し訳ありません、私はいつもパイプについて語ります。 (実際には英語は私の第3言語で、2番目のahahahをスペイン語にしています) –

答えて

1

同じパイプを使用して各子と通信しようとすると、問題が発生します。

プログラムの先頭に2つのパイプを作成します。ループの最初の反復では、親フォークと子は親のすべてのオープンファイル記述子を継承します。子は必要のないパイプの端を閉じ、親はパイプの端を閉じますは必要ありません。コミュニケーションは意図どおりに起こります(想像してみてください)。

しかし、ループの2番目の繰り返しを考えてみましょう。もう一度フォークし、その子は再び親の開いているファイル記述子を継承します。しかし、今では、子が使用したいファイル記述子は、ループの以前の反復で親によって閉じられました。私はちょっと子供がEPIPEの代わりにEBADFというファイル記述子を使用しようとすると驚いていますが、読み込みに失敗しても驚くことはありません。

一番きれいなことは、一組のパイプを再利用するのではなく、各子に新しいパイプのペアを作成することです。あなたがそれをちょうど1つのペアで動作させたいならば、親プロセスはパイプの終わりを閉じるのを避けなければなりません(あなたが望むならば、子プロセスはそれらのコピーを閉じるかもしれません)。

関連する問題