2017-02-24 1 views
0

Bonjour, Je dois développer ce programme qui crée 4 enfants et, séquentiellement, faites-les faire une opération simple. Le premier fera la somme, le second le reste, le troisième la multiplication et le quatrième la division. Le père écrira sur la socket la chaîne avec le nombre qu'il veut que ses enfants "calculent", et chaque enfant devrait lire cette chaîne, extraire les nombres et les opérations. Évidemment, étant deux tuyaux, il est nécessaire que le père écrit à chaque fois la chaîne, à cause de la lecture dans l'enfant. Je ne comprends pas vraiment pourquoi à la deuxième itération, je reçois un SIGPIPE sur l'écriture du père. Quelqu'un peut-il m'expliquer pourquoi? J'ai perdu 3 jours sur le débogage, mais je n'ai rien trouvé. Merci beaucoup.SIGPIPE dans la messagerie bidirectionnelle avec deux tuyaux

#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

Remarque: vous mentionnez l'écriture du parent dans une socket, mais vous ne semblez utiliser aucun socket, seulement des tuyaux. –

+0

Je suis sûr que, avec l'anglais comme langue seconde, il ne fait que se tromper. – BaseZen

+0

Désolé, je parle toujours des tuyaux. (En fait l'anglais est ma troisième langue et l'espagnol le deuxième ahahah) –

Répondre

1

Vous rencontrez des problèmes en essayant d'utiliser les mêmes tuyaux pour communiquer avec chaque enfant.

Vous créez deux tuyaux au début du programme. Lors de la première itération de la boucle, les parenthèses parentales et l'enfant héritent de tous les descripteurs de fichiers ouverts du parent. L'enfant ferme les extrémités de tuyau dont il n'a pas besoin, et le parent ferme les extrémités de tuyau il n'a pas besoin de. La communication se passe comme prévu (j'imagine) - tout va bien jusqu'à présent.

Mais considérons maintenant la deuxième itération de la boucle. Vous recommencez et l'enfant hérite à nouveau des descripteurs de fichiers ouverts du parent. Mais maintenant, les descripteurs de fichiers que l'enfant veut utiliser ont été fermés par le parent lors de l'itération précédente de la boucle. Je suis un peu surpris que l'enfant obtienne alors un EPIPE au lieu d'un EBADF lorsqu'il essaie d'utiliser ces descripteurs de fichier, mais je ne suis pas du tout surpris que sa tentative de lecture échoue. La meilleure chose à faire serait de créer une nouvelle paire de tuyaux pour chaque enfant, au lieu d'essayer de réutiliser un ensemble de tuyaux. Si vous voulez le faire fonctionner avec juste une paire, alors le processus parent doit éviter de fermer l'une des extrémités du tube (bien que les processus fils puissent fermer leurs copies, si vous le souhaitez).