Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

Tubes et processus fils


Sujet :

Linux

  1. #1
    Membre à l'essai
    Tubes et processus fils
    Bonjour, j'essaie de mettre en place un programme C qui permet de réaliser ceci :
    Un processus père P0 lit dans un fichier un texte de plusieurs dizaines de caractères. Il le segmente en paquets de 8 caractères et numérote chaque paquet.
    Au fur et à mesure que les paquets sont constitués, le père transmet le paquet à l'un de ses 3 fils P1, P2, P3 choisi aléatoirement. Chacun de ses fils traite un paquet reçu en le retenant aléatoirement entre 1 et 4 secondes, puis le transmet à P4.

    P4 réordonne les paquets reçus et affiche le message lorsque tous les paquets ont été reçus.

    Voici le code source que j'ai terminé de réaliser mais qui comporte des erreurs, en effet, à la fin les processus fils transmettent 1 paquet au processus P4 par un tube : normalement il doit stocker tous les paquets qu'il reçoit, mais là dans mon code source, il ne garde en mémoire que le dernier paquet envoyé :
    Code c :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
     
    #include <stdlib.h>
    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
     
    #define TAILLE 20
    int subString(const char *chaine, int debut, int fin, char *result){
        result[fin+1-debut]='\0';
        memcpy(result,(char *)chaine+debut,fin+1-debut);
        return (fin+1-debut);
    }
    int Random (int _iMin, int _iMax) //Permet de génerer un nombre entre _iMin et _iMax
    {
        return (_iMin + (rand () % (_iMax-_iMin+1)));
    }
     
    int main(){
    	int i=0,ret,pidf1,pidf2,pidf3,pidf4;
    	char tab[50];
    	int p_choisi;
    	char chainecouper[10];
    	char reception1[50]="";
    	char reception2[50]="";
    	int p1[2],p2[2],p3[2],p4[2];
     
    	FILE* fichier = NULL;
    	char chaine[50] = "";
     
         fichier = fopen("test.txt", "r");
         if(pipe(p1)||pipe(p2)||pipe(p3)||pipe(p4))
         {
            perror("erreur de creation du tube");
            exit(1);
         }
        if (fichier != NULL)
        {
            fgets(chaine, 20, fichier); 
            printf("Texte ! %s\n", chaine); // On affiche la chaîne
            printf("Taille %d\n", strlen(chaine)-1);
            fclose(fichier);
        }
     
        pidf1=fork();
        pidf2=fork();
        pidf3=fork();
        pidf4=fork();
     
         while(i<strlen(chaine)-1){
         	if((pidf1>0) && (pidf2>0) && (pidf3>0) & (pidf4>0)) {
         		subString(chaine,i,i+7,chainecouper);
         	}
         	//P1 ou P2 ou P3 reçoit le paquet et le mémorise
         	p_choisi=Random(1,3);
         	//printf("Choix %d\n",p_choisi);
    	switch(p_choisi){
            	case 1:
    	    	   if(pidf1==0){//nous sommes dans le fils1 
    			read(p1[0],reception1,TAILLE);
    			write(p4[1],reception1,TAILLE);
    			sleep(Random(1,4));
    			printf("\t le fils 1 a lu %s dans le tube p1 et ecrit cette valeur dans le tube p4\n",reception1);
    			exit(0);
    	    	   }
    	    	   if((pidf1>0) && (pidf2>0) && (pidf3>0) & (pidf4>0)){ //sinon nous sommes dans le père
    			write(p1[1],chainecouper,strlen(chainecouper));
    			printf("le pere ecrit %s dans p1\n", chainecouper);
    			wait(0);
    	    	   }
    	    	   if(pidf4==0){
    			sleep(Random(1,3));
    			printf("le fils 4 reordonne les paquets\n");
    			exit(0);
    	    	   }
    	    	break;
            	case 2:
    	    	   if(pidf2==0){
                	   //le fils 2 lit dans le tube du père
    			read(p2[0],reception1,TAILLE);
    			write(p4[1],reception1,TAILLE);
    			sleep(Random(1,4));
    			printf("\tle fils 2 a lu %s dans le tube p1 et ecrit cette valeur dans le tube p4\n",reception1);
    			exit(0);
                	   }
    	    	   if((pidf1>0) && (pidf2>0) && (pidf3>0) & (pidf4>0)) { //sinon nous sommes dans le père
    			write(p2[1],chainecouper,strlen(chainecouper));
    			printf("le pere ecrit %s dans p2\n",chainecouper);
    			wait(0);
    	          }
    	    	  if(pidf4==0){
    			sleep(Random(1,3));
    			printf("le fils 4 reordonne les paquets\n");
    			exit(0);
    	    	  }
                	break;
    		case 3:
                	   if(pidf3==0){
                 	   //le fils 1 lit dans le tube du père
    			read(p3[0],reception1,TAILLE);
    			write(p4[1],reception1,TAILLE);
    			sleep(Random(1,4));
    			printf("\tle fils 3 a lu %s dans le tube p3 et ecrit cette valeur dans le tube p4\n",reception1);
    			exit(0);
                	  }
    	    	  if((pidf1>0) && (pidf2>0) && (pidf3>0) & (pidf4>0)) { 
    		  //sinon nous sommes dans le père
    			write(p3[1],chainecouper,strlen(chainecouper));
    			printf("le pere ecrit %s dans p3\n",chainecouper);
    			wait(0);
    	    	  }
    	    	  if(pidf4==0){
    	    		sleep(Random(1,3));
                		printf("le fils 4 reordonne les paquets\n");
    	    		exit(0);
    		  }
                	break;
            }//Fin du Switch
     
         	if((pidf1>0) && (pidf2>0) && (pidf3>0) & (pidf4>0)) {
         		//affichage du resultat de la chaine coupée
         		printf("Temp original %s\n",chainecouper);
         		printf("\n");
         		read(p4[0],tab,50);
         		printf("\tContenu du tube 4 %s\n", tab);
         		printf("Indice i %d\n",i);
         		i=i+8;
         	}
     
     
         }//Fin de la boucle while
         printf("FIN\n ");
     }


    Pouvez vous m'aider à résolver ce petit problème de tubes ?
    Merci d'avance.

  2. #2
    Membre à l'essai
    Lol ça sent un peu le pompage là... Tu serais pas en L3 MIAGe a Lyon 1 toi un peu? xD

    GRRRIIIIIIIILLLLLLéééééé

  3. #3
    Expert éminent sénior
    Citation Envoyé par Jopzeut

    Voici le code source que j'ai terminé de réaliser mais qui comporte des erreurs
    En effet :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    pipe.c: In function 'main':
    pipe.c:31: warning: implicit declaration of function 'pipe'
    pipe.c:44: warning: implicit declaration of function 'fork'
    pipe.c:49: warning: comparison between signed and unsigned
    pipe.c:59: warning: implicit declaration of function 'read'
    pipe.c:60: warning: implicit declaration of function 'write'
    pipe.c:61: warning: implicit declaration of function 'sleep'
    pipe.c:68: warning: implicit declaration of function 'wait'
    pipe.c:24: warning: unused variable 'reception2'
    pipe.c:19: warning: unused variable 'ret'
    pipe.c:132: warning: control reaches end of non-void function



    en effet, à la fin les processus fils transmettent 1 paquet au processus P4 par un tube : normalement il doit stocker tous les paquets qu'il reçoit, mais là dans mon code source, il ne garde en mémoire que le dernier paquet envoyé
    Ca c'est un problème algorithmique. Qu'est-ce que tu ne comprends pas ? Il suffit de faire une liste chaînée ou un tableau qui contient tous les paquets.

    Ensuite pour le code :

    - Pas d'appel à srand.

    - Si un des pipes ne s'ouvre pas, tu ne refermes pas proprement les autres.
    - Si les pipes s'ouvrent, il faut fermer les côtés qu'on utilise pas. Du coup, le premier fils doit fermer le côté écriture de p1, p2,p3 et le côté lecture de p4. Ci-dessous la bonne facon de créer un fork, du coup, chaque fils aura juste à fermer son propre pipe et celui menant à p4.

    - Si fichier == NULL, chaine sera utilisée non initialisée


    Code c :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        pidf1=fork();
        pidf2=fork();
        pidf3=fork();
        pidf4=fork();


    - Aucun test sur le retour des forks, pire, tu va avoir en fait 16 processus parce que tu n'as pas fait les choses correctement. Il faut faire ceci :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    pid1 = fork();
    if(pid1 != 0) {
       /* Pere */
       pid2 = fork();
    }
    else {
      /* Fils */
      ...
    }


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
         while(i<strlen(chaine)-1){
         	if((pidf1>0) && (pidf2>0) && (pidf3>0) & (pidf4>0)) {
         		subString(chaine,i,i+7,chainecouper);
         	}

    - Tu vas sortir de la longueur de chaîne et donc provoquer un comportement indéterminé car tu ne fais aucun test dans ta fonction subString pour vérifier que le memcpy sera correct.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
         	//P1 ou P2 ou P3 reçoit le paquet et le mémorise
         	p_choisi=Random(1,3);

    Génial, les processus fils doivent attendre d'avoir le bon random pour attendre leur paquet... Avec ma facon de faire les forks, on sait tout de suite où commence et se termine le code des fils.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    			read(p1[0],reception1,TAILLE);
    			write(p4[1],reception1,TAILLE);
    		        ....
    			write(p1[1],chainecouper,strlen(chainecouper));

    - Le père écrit un certain nombre de caractères qu'on suppose < TAILLE mais on envoit TAILLE caractères à p4 ?

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
         }//Fin de la boucle while
         printf("FIN\n ");
     }


    Manque un return, la fermeture des pipes, le wait du père, l'exit des fils...

    Jc

  4. #4
    Nouveau Candidat au Club
    Bonjour,

    je me demandais si tu as réussi a réaliser le programme? si oui ça serai trop sympa si vous me donniez quelque indications pouvant m'aider a le faire fonctionner.. Merci infiniment!