/****************************************************************************** ** ** Communication par tubes. ** ----------------------- ** Ce programme se compose de trois processus et quatre tubes. Le processus ** parent est chargé de lire les caractères en provenance de l'entrée standard, ** d'envoyer les chiffres au premier enfant (par l'intermédiaire du premier ** tube) et les lettres au second (par l'intermédiaire du troisième tube). ** Une fois la fin de fichier atteinte, les enfants renvoient leurs résultats ** au parent (par l'intermédiaire respectivement des deuxième et troisième ** tubes). Le parent affiche ensuite les résultats. ** ** © 2002, Éric Renault pour l'Institut National des Télécommunications. ** © 2003, Denis Conan ** ******************************************************************************/ #include #include #include #include #include #define TUBE_DC 0 /* Distributeur -> Chiffre */ #define TUBE_CD 1 /* Chiffre -> Distributeur */ #define TUBE_DL 2 /* Distributeur -> Lettre */ #define TUBE_LD 3 /* Lettre -> Distributeur */ #define TUBE_NOMBRE 4 #define TUBE_LIT 0 #define TUBE_ECRIT 1 #define TUBE_TOTAL 2 /* ** Écriture d'un entier. */ void ecrit_entier (int fichier, int entier) { int retour; do { retour = write(fichier, &entier, sizeof(int)); assert(retour != -1); } while (retour == 0); } /* ** Lecture d'un entier. */ int lit_entier(int fichier) { int retour, entier; do { retour = read(fichier, &entier, sizeof(int)); assert(retour != -1); } while(retour == 0); return entier; } /* ** Somme des chiffres. */ void chiffre(int lit, int ecrit){ int car, somme = 0; /* Lecture des chiffres et somme. */ while((car = lit_entier(lit)) != EOF) { somme += (car - '0'); } /* Renvoi du résultat. */ ecrit_entier(ecrit, somme); } /* ** Fréquence des lettres. */ void lettre(int lit, int ecrit){ int car, frequence['z' - 'a' + 1], i; /* Initialisation. */ for (i = 'a' ; i <= 'z' ; i ++) { frequence[i - 'a'] = 0; } /* Lecture des lettres et incrément des fréquences. */ while ((car = lit_entier(lit)) != EOF) { frequence[tolower(car) - 'a'] ++ ; } /* Renvoi du résultat. */ for (i = 'a' ; i <= 'z' ; i ++) { ecrit_entier(ecrit, frequence[i - 'a']); } } /* ** Distribution des caractères et affichage des résultats. */ void distributeur(int ecrit_c, int lit_c, int ecrit_l, int lit_l) { int car, i; /* Distribution des caractères. */ do { car = getchar(); if (isalpha(car) || (car == EOF)) { ecrit_entier(ecrit_l, car); } if (isdigit(car) || (car == EOF)) { ecrit_entier(ecrit_c, car); } } while(car != EOF); /* Lecture et affichage de la somme. */ printf("Somme : %d", lit_entier(lit_c)); /* Lecture et affichage des frequences. */ for (i = 'a' ; i <= 'z' ; i ++) { printf(" ; %c : %d", i, lit_entier(lit_l)); } printf("\n"); } /* ** Mise en place des tubes et des processus. */ int main(int argc, char* argv[]) { int tube[TUBE_NOMBRE][TUBE_TOTAL]; int i, retour; /* Initialisation des tubes. */ for(i = 0 ; i < TUBE_NOMBRE ; i ++) { retour = pipe(tube[i]); assert(retour != -1); } /* Création des enfants et lancement des taches associées. */ switch(fork()) { case -1 : exit(1); case 0 : chiffre (tube[TUBE_DC][TUBE_LIT], tube[TUBE_CD][TUBE_ECRIT]); break; default : switch(fork()) { case -1 : exit(2); case 0 : lettre(tube[TUBE_DL][TUBE_LIT], tube[TUBE_LD][TUBE_ECRIT]); break; default : distributeur(tube[TUBE_DC][TUBE_ECRIT], tube[TUBE_CD][TUBE_LIT], tube[TUBE_DL][TUBE_ECRIT], tube[TUBE_LD][TUBE_LIT]); } } /* Fermeture des tubes. */ for(i = 0 ; i < TUBE_NOMBRE ; i ++) { retour = close(tube[i][TUBE_LIT]); assert(retour != -1); retour = close(tube[i][TUBE_ECRIT]); assert(retour != -1); } /* Tout s'est bien terminé. */ exit(0); }