Processus 2022 2
Processus 2022 2
Processus 2022 2
• Un tube de communica.on est un tuyau (pipe) dans lequel deux ou plusieurs processus peuvent
échanger des informa.ons : un peut écrire des données et un autre peut lire
• Principe :
• Un processus écrit dans descripteur[1]
• Un autre va lire les mêmes données dans descripteur[0]
• Seuls les descendants du processus créateur du tube et lui-même peuvent l’u.liser
• Toute lecture est destruc.ve
• Le tube est unidirec.onnel
Communica)on inter-processus par tube
• Communica)on via un tube (On suppose que le père écrit dans le tube alors que le fils lit)
1. Le processus crée le tube
2. Le processus fait un appel à fork() pour créer un fils.
3. Les deux processus père et fils possèdent alors chacun un descripteur en lecture et en
écriture sur le tube.
4. Le processus père ferme son descripteur en lecture. Le processus fils ferme son descripteur
en écriture sur le tube.
5. Le processus père peut écrire sur le tube ; les valeurs écrites pourront être lues par le fils.
Communica)on inter-processus par tube
• ssize_t read(int fd0, void *buf, size_t taille)
lit jusqu’à taille octets depuis le descripteur de fichier fd0 dans le tampon pointé par buf
Par exemple,
char buf[100];
int p[2];
n=read(p[0], buf, 20); à n <= 20
char buf[100];
int p[2];
sprintf(buf, "texte à écrire ");
write(p[1], buf, 20);
• S’il n’y a aucun lecteur sur le tube (tous les descripteurs en lecture sont fermés) à erreur fatale, le
processus écrivain renvoie le signal SIGPIPE
• Sinon, s’il y a de la place , les caractères sont écrits à write renvoie le nombre de caractères
Sinon à écriture bloquante jusqu’à ce qu’il y ait de la place
Ø ./tube
création d’un tube
Fermeture sortie dans le pere (pid = 744)
Fermeture entree dans le fils (pid = 746)
Le fils (746) a lu : Message du pere (744) au fils
Communica)on inter-processus par tube
• Transmission binaire
Exemple qui saisit une valeur au clavier dans le père et transmet la racine carrée de ce nombre en
tant que double au fils
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <math.h>
int main() {
pid_t fils;
int tube[2];
double x, y, z;
Communica)on inter-processus par tube
puts("Créa+on d'un tube");
if (pipe(tube) != 0) /* pipe */
{
fprin=(stderr, "Erreur dans pipe\n");
exit(1);
}
switch(pid_fils = fork()) /* fork */
{
case -1 : perror("Erreur dans fork\n"); exit(errno);
case 0 : /* processus fils */
close(tube[1]);
read(tube[0], &z, sizeof(double));
prin=("Le fils (%d) a lu : %.2f\n", getpid(), z); break;
Communica)on inter-processus par tube
default : /* processus père */
prin4("Fermeture sor9e dans le père (pid = %d)\n", getpid());
close(tube[0]);
puts("Entrez x :");
scanf("%lf", &x);
y = sqrt(x);
write(tube[1], &y, sizeof(double));
wait(NULL); break;
}
return 0;
}
Communica)on inter-processus par tube
• Le programme suivant lit des caractères sur l’entrée standard et envoie et envoie les lettres et
chiffres à son processus fils. Le fils compte les lettres et les chiffres et affiche le résultat. Le père
attend la terminaison du fils.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
int main() {
pid_t retour ;
int tube[2], lettre = 0, chiffre = 0 ;
char k ;
if (pipe (tube) == -1) {
perror ("creation pipe impossible\n") ; exit (1) ;
}
Communica)on inter-processus par tube
switch (retour = fork ()) {
case -1 : perror ("Crea9on impossible") ;
exit(1) ;
case 0 : prinA ("processus fils\n") ;
close (tube[1]) ;
while (read (tube[0], &k, 1) >0)
if (isdigit (k)) chiffre++ ;
else leMre++ ;
prinA ("%d chiffres recus\n", chiffre) ;
prinA ("%d leMres recues\n", leMre) ;
exit (0) ;
default :
Communica)on inter-processus par tube
prin% ("pere: a cree processus %d\n", retour) ;
close (tube[0]) ;
while (read (0, &k, 1) >0) /* lecture du clavier */
if (isalnum(k)) write (tube[1], &k, 1) ;
/* le tube est ici ferme en ecriture : un read sur le tube vide retournera 0 dans le
processus fils */
close (tube[1]) ;
wait (NULL) ;
prin% ("pere: a recu terminaison fils\n") ;
}
}
Communica)on inter-processus par tube
Ø ./tube_3
pere: a cree processus 346
processus fils
ztb;628?.rt5^D
4 chiffres recus
5 le@res recues
pere: a recu terminaison fils
Communica)on inter-processus par tube
• Communication bi-directionnelle entre père et fils (il faut 2 tubes !)
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main () {
int pip1[2]; int pip2[2];
pid_t pid_fils;
char chaine1[7], chaine2[5];
/* Création des tubes */
if(pipe(pip1) == -1) {
perror("pipe 1");
exit(1);
}
Communica)on inter-processus par tube
if(pipe(pip2) == -1) {
perror("pipe 2");
exit(2);
}
/* créa9on processus */
pid_fils = fork();
if (pid_fils == -1) {
perror ("Crea9on impossible") ;
exit(3) ;
}
if (pid_fils > 0) {
/* tube père vers fils */
/* fermé en lecture */
close (pip1[0]);
/* second tube fils vers père */
/* fermé en écriture */
close (pip2[1]);
Communica)on inter-processus par tube
/* envoi message au fils par le tube 1*/
if(write(pip1[1],"hello",5)!=5) {
fprinB(stderr,"père: erreur en écriture\n");
exit(4);
}
/* ANente de la réponse du fils par le tube 2 */
if(read(pip2[0],rep,7)!=7) {
fprinB(stderr,"fils: erreur lecture\n");
exit(5);
}
prinB("message du fils: %s\n",rep);
wait(&status);
}
Communica)on inter-processus par tube
else {
/*fermeture du tube 1 en écriture */
close(pip1[1]);
/* fermeture du tube 2 en lecture */
close(pip2[0]);
/* a>ente d’un message du père */
if(read(pip1[0],mesg,5)!=5) {
fprinF(stderr,"fils: erreur lecture\n");
exit(6);
}
prinF("la chaine reçue par le fils est: %s\n",mesg);
/* envoi d’un message au père */
if(write(pip2[1],"bonjour",7)!=7) {
fprinF(stderr,"fils: erreur ecriture\n"); exit(7);
}
exit(0);
}
}
Entrées-sor*es et tubes
• On peut lier la sortie d’un tube à stdin (1) ou l’entrée d’un tube à stdout (2)
• (1) à toutes les informations qui sortent du tube arrivent dans le flot d’entrée standard et peuvent être lues avec
scanf, gets,…
• (2) à toutes les informations qui sortent par stdout sont écrites dans le tube. On peut utiliser printf, puts,…
• int dup2 (int ancien descripteur, int nouveau descripteur) permet de dupliquer les entrées de la
table des descripteurs
• Duplication des descripteurs
• Rediriger les entrées-sorties standard d’un processus sur un tube
ancien descripteur : descripteur[0] si on veut lier la sortie
descripteur[1] si on veut lier l’entrée