2017-02-24 8 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

제 2 언어로서의 영어로, 그는 단지 말하기가 잘못되었다고 확신합니다. – BaseZen

+0

죄송합니다, 저는 항상 파이프에 대해 말하고 있습니다. (실제로 제 영어는 제 3 언어이고 스페인어는 두 번째 아아하입니다) –

답변

1

동일한 파이프를 사용하여 각 어린이와 통신하려고하면 문제가 발생합니다.

두 개의 파이프를 프로그램의 시작 부분에 만듭니다. 루프의 첫 번째 반복에서 부모 분기가 발생하고 자식은 모든 부모의 열린 파일 설명자를 상속합니다. 아이가 필요하지 않은 파이프 끝을 닫고 부모가 파이프 끝을 닫습니다. 은 필요하지 않습니다. 의사 소통은 의도 한대로 진행됩니다 (상상해보십시오).

이제 루프의 두 번째 반복을 고려하십시오. 다시 포크하고 자식은 부모의 열린 파일 설명자를 다시 상속받습니다. 그러나 이제는 자식이 사용하기를 원하는 파일 설명자가 이전 루프 반복에서 부모에 의해 닫혔습니다. 나는 아이들이 파일 설명자를 사용하려고 시도 할 때 EBADF 대신에 EPIPE을 얻게되는 것에 조금 놀랐지 만 읽기 시도가 실패한다는 것에 놀랍지는 않습니다.

할 일 중 가장 청결한 일은 한 세트의 파이프를 재사용하는 대신 각 자식에 대해 새로운 파이프 쌍을 만드는 것입니다. 한쌍으로 만 작동하게하려면 부모 프로세스가 파이프 끝을 닫지 않아야합니다 (원하는 경우 하위 프로세스가 사본을 닫을 수 있음).