Communiquer entre processus avec des pipe

akrogames Messages postés 32 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 8 octobre 2009 - 8 oct. 2009 à 16:53
uaip Messages postés 1466 Date d'inscription mardi 20 février 2007 Statut Membre Dernière intervention 7 février 2011 - 8 oct. 2009 à 22:01
Bonjour,


Je souhaite réaliser un programme pour m'entrainer à créer des anneaux avant de passer à la programmation socket. Mon objectif : faire passer un entier qui s'incrémente sur chaque fils grâce à un jeton. Je dois créer une topologie virtuelle avec des fork() et faire circuler un jeton qui contient un entier qui s'incrémente en passant dans chaque processus.

J'ai besoin de votre aide au niveau algorithmique. En effet j'y ai réfléchi ce soir et je ne voit pas comment faire pour mettre en attente un processus qui doit en attendre un autre. C'est mon premier problème. Mon second est le suivant : qu'elle sera l'identifiant unique de chaque processus ? Comment les récupérer en C ?

Alors voilà ce que je souhaite faire :

Pere > Fils1 > Fils2 > Fils3> Fils4 > Fils5 > Fils1 > Fils2 etc...

Jusqu'à ce que le jeton qui transite sur l'anneau qui contient l'entier atteigne 50. Il s'incrèmente sur chaque Fils de +1. Vous comprenez ?


J'ai réalisé ce code où les processus ont tous le même père mais je suis obligé de faire un exit chaque fois ?
Alors comment faire pour els faire communiquer entre eux ?

Mon code :
#include <stdio.h>
#include 
#include <sys/types.h>
#include <stdlib.h>

#define lire 0
#define ecrire 1

int main(int argc,char **argv)
{
//Gestion des clients
int pid[5]; //Liste des clients fils
int f[5];
int i;
int pid0;
int ppid;

//Gestion des tubes
int f1f2[2];
int f2f3[2];
int f3f4[2];
int f4f5[2];
int f5f1[2];

//Creation des differents tubes
if(pipe(f1f2) == -1)
{
printf("ERREUR : INITIALISATION IMPOSSIBLE DU TUBE ENTRE FILS 1 et FILS 2\n");
return 1;
}
if(pipe(f2f3) == -1)
{
printf("ERREUR : INITIALISATION IMPOSSIBLE DU TUBE ENTRE FILS 2 et FILS 3\n");
return 1;
}
if(pipe(f3f4) == -1)
{
printf("ERREUR : INITIALISATION IMPOSSIBLE DU TUBE ENTRE FILS 3 et FILS 4\n");
return 1;
}
if(pipe(f4f5) == -1)
{
printf("ERREUR : INITIALISATION IMPOSSIBLE DU TUBE ENTRE FILS 4 et FILS 5\n");
return 1;
}
if(pipe(f5f1) == -1)
{
printf("ERREUR : INITIALISATION IMPOSSIBLE DU TUBE ENTRE FILS 5 et FILS 1\n");
return 1;
}

for(i=1;i<6;i++)
{
f[i] = fork();
if(f[i] < 0 )
{
printf("ERREUR : CREATION IMPOSSIBLE DU FILS 1\n");
return 1;
}
else if(f[i] == 0)
{
pid[i] = getpid();
ppid = getppid();
printf("FILS %d CREER AVEC LE NUMERO : %d PERE=>%d\n",i,pid[i],ppid);
exit(i);
}		
}



exit(0);



}


Bonne journée

1 réponse

uaip Messages postés 1466 Date d'inscription mardi 20 février 2007 Statut Membre Dernière intervention 7 février 2011
8 oct. 2009 à 22:01
Salut,

Tu oublies une condition après la création du fork():
fork() < 0 -> erreur
fork() 0 -> processus fils (id_pere getppid() et id_fils = getpid())
fork() > 0 -> processus père (id_pere getpid() et id_fils retour de fork())
Pour la duplication du code, blabla, je pense que tu as compris.

A ta place, j'enlèverai la boucle et ferai du cas pas cas, car dans chaque processus, tu dois fermer une extrémité des tubes (avec close(descripteur);).
Pour les faire communiquer entre eux, suffit d'utiliser les fonctions read() et write().

En gros, de mémoire (car je ne prog pas énormément sous linux), voici ce que donnerait un échange entre 2 processus père et fils (le père envoie un entier au fils):
int main() {
int descripteur[2]; //Descripteur du tube anonyme
//Création du tube anonyme
if (pipe(descripteur) == -1) { puts("Erreur de création du tube"); exit(1); }
//Duplication du processus
pid_t pid=fork();
if (pid < 0) { puts("Erreur de duplication du processus") exit(1); }
//Cas du processus fils
if (pid == 0) {
close(descripteur[1]); //Fermeture de l'entrée du tube
//Lecture du tube
size_t res;
int nbr;
res=read(descripteur[0],(int*)&nbr,sizeof(int));
//Vérification des erreurs
//Cas d'une erreur système
if (res < 0) { puts("Erreur de lecture du tube"); exit(1); }
//Cas où le processus écrivain a fermé son extrémité du tube
else if (res != sizeof(int)) { puts"Erreur de lecture du tube"); exit(1); }
//Sinon, tout s'est bien passé, affichage de l'entier lu
printf("Entier lu: %d\n",nbr);
close(descripteur[0]; //Fermeture du descripteur
}
//Cas du processus père
else if (pid > 0) {
close(descripteur[0]); //Fermeture de la sortie du tube
//Ecriture dans le tube
size_t res;
int nbr=5; //Entier écrit
res=write(descripteur[1],(int*)&nbr,sizeof(int));
//Vérification des erreurs
if (res != sizeof(int)) { puts("Erreur d'écriture dans le tube"); exit(1); }
close(descripteur[1]; //Fermeture du descripteur
}
}


Voilà comment on communique dans le cas d'un tube anonyme (de mémoire, il y a sans doute des erreurs).

Ensuite, pour attendre, plusieurs possibilités : wait(), waitpid(), pause(), (d'autres, à oublier dans ton cas: sleep(), alarm(), ...)
Les problèmes :
- wait() attend la fin de n'importe quel processus
- waitpid() attend la fin d'un processus fils (donc à utiliser uniquement pour le processus père)
- pause() attend n'importe quel signal (ce qui permet à l'autre processus de le réveiller en lui envoyant un signal, mais si c'est le système qui, pour une raison quelconque, lui en envoie un, c'est fichu)

Et là... désolé mais j'ai plus le courage de réfléchir ce soir

Mais dis moi, ce ne serait pas un TP ton truc (tu dis "je dois faire ça") ? Si c'est un projet personnel, pourquoi ne pas utiliser les segments de mémoire partagée (+ éventuellement les sémaphores) ? Ce serait, à mon avis, plus simple que les tubes.


En fait, tu as un exempleconcret de tube anonyme ici

Bonne chance !

Cordialement, uaip.
0
Rejoignez-nous