SlideShare une entreprise Scribd logo
Communication entre processus
et
Synchronisation des processus
M. Ben Salah
1
- Les processus concurrents peuvent être :
- coopératifs : dépendants les uns des autre
- ou indépendants
- Les processus peuvent coopérer :
- par communication de données
- ou en partageant des ressources (mémoire, …)
 Besoin de communiquer entre processus pour échanger des données et
informations,
 Besoin de synchronisation .
I- Communication entre processus
● Il existe plusieurs moyens de communication entre processus :
- Par le biais d’un fichier
- tube
- Signaux
- Par une zone mémoire
- Files de messages (MSQ)
I- Communication entre processus
- Files de messages (MSQ)
4
I-1- Communication par tubes
5
● Objectif de cette parties :
permettre la communication entre processus.
Communication par tubes
● Définition du tube (pipe) :
Un tube est un fichier spécial géré par le système au niveau du système de
gestion de fichiers. Il permet la communication entre deux processus de la
manière suivante : un processus peut écrire des données dans le tube et un
autre processus peut lire ces données.
Processus écrivain :
p1
Processus lecteur :
P2
p2
6
● Principe :
deux extrémités (deux descripteurs) : une permettant d’´ecrire des données par
le processus écrivain l’autre permettant de les lire par le processus lecteur
● On lit/écrit dans un tube comme on lit/écrit dans un fichier ordinaire
● Communication d’un flot continu de caractères
- communication en mode flot (opposé à datagramme) :
opérations de lecture indépendantes des opérations d’écriture
● Le fonctionnement est de type FIFO :
- premier caractère écrit, premier caractère lu
- Il n’est pas possible de lire un octet sans avoir lu tous ceux qui le précèdent
● Caractéristiques techniques :
Communication par tubes
● Opération de lecture est destructive :
une information lue est extraite du tube
● Si un tube est vide, ou si on a plus écrivains (extrémité d’écriture fermé)
la lecture renvoie la valeur 0 (fin de fichier atteinte)
● Un processus qui écrit dans un tube qui n’a plus de lecteurs (extrémité de
Lecture fermée ) reçoit le signal SIGPIPE
● Système assure la synchronisation entre le lecteur et l’écrivain :
Bloque le processus lecteur quand le tube est vide.
Bloque le processus ´écrivain quand le tube est plein 7
● Deux types de tubes :
1- Tubes anonymes
2- Tubes nommés
Communication par tubes
8
P1 (écrire) P2 (lire)
Tubes anonymes
● Caractéristiques :
● Un tube annonyme est un fichier particulier :
- Il n’a pas de nom dans l’arborescence des fichiers
- Il est connu par deux descripteurs (lecture, écriture)
● Permet la communication entre processus qui ont un lien de parenté : les deux
processus doivent connaitre le même canal afin de communiquer
== > héritage du descripteur
desc[1] desc[0]
9
== > héritage du descripteur
● temporaires (volatile) : ils n’existent que le temps d’exécution du processus
qui les crée.
● Création : par appel systéme pipe, déclarée dans unistd.h
● Primitive :
#include <unistd.h>
int desc[2];
int pipe(int desc);
Processus écrivain Processus lecteur
Création de tubes anonymes
retourne 0 si le tube est donc créé, -1 si en cas d’echec
► l'appel pipe retourne deux descripteurs :
- desc[0] : Pour la lecture. C’est la sortie du tube dans laquelle on peut
lire des données. Il doit être ouvert pour la lecture seule
- desc[1] : Pour l’écriture. C’est l’entrée du tube dans laquelle on peut
écrire des données. Il doit être ouvert pour l’écriture seule
desc[1]
desc[0]
10
● Les descripteurs du tube doit être partagé par les processus communiquant
== > l’appel pipe doit se faire avant fork() !!!
desc[0]
Création de tubes anonymes
desc[1]
11
● Le tube doit être créé avant le fork pour que les descripteurs du tube soient
hérités par les processus qui vont communiquer via le tube (héritage des
descripteurs lors du fork() ) :
Un tube est créé dans un seul processus. Le processus fils ne peut pas deviner
les valeurs du tableau descripteur. Il faut donc appeler la fonction pipe avant
d’appeler la fonction fork. Cela permet au processus père et le(s) processus fils
(sa descendance) d’avoir les mêmes descripteurs de tubes, et pourront donc
communiquer entre eux.
Création de tubes anonymes et fork()
communiquer entre eux.
● Rappelons qu’un tube ne permet de communiquer que dans un seul sens. Si l’on
souhaite que les processus communiquent dans les deux sens, il faut créer deux
pipes.
12
Si le processus père écris, le processus fils lis :
Partage d’un tube
Processus lecteur
(exemple : fils)
hérite de desc[1] et desc[0]
desc[1] desc[0]
Processus écrivain
(exemple : père)
desc[1] desc[0]
close(desc[0])
close(desc[1])
1) pipe()
2) fork()
13
int close(int desc);
== > - close(desc[1]) dans le processus lecteur
- close(desc[0]) dans le processus écrivain
tube
Extrémité d’écriture
Extrémité de lecture
● Il faut fermer le descripteur inutile dans chaque processus : primitive close
-- > sinon interblocage
close(desc[0])
close(desc[1])
Ecriture/lecture dans un tube anonyme
● Pour écrire dans un tube : write
● Un tube à une capacité max : notée PIPE_BUF. C’est la taille du tube sur
le système == > <limits.h>
● le signal SIGPIPE est envoyé au processus qui exécute write si le tube n’a
● Primitive :
int write(int desc[1], const void *bufW, int nb_ecris);
- nb_ecris : nombre d’octet à écrire
- bufW : pointeur générique vers la mémoire contenant les données à écrire
- l’appel retourne en résultat le nombre d’octets écris
● le signal SIGPIPE est envoyé au processus qui exécute write si le tube n’a
été ouvert en lecture par aucun autre processus (pas de lecteur). Ce signale
termine le processus.
14
● La lecture : read
● Primitive :
int read(desc[0], char *buffR, int taille_lecture);
- BufR : pointeur vers la mémoire contenant les données à lire
- taille_lecture : le nombre d’octets qu’on souhaite lire depuis la sortie du tube
desc [0] à partir du tampon bufR
# include <stdio.h>
# include<sys/wait.h>
# include<unistd.h>
# include <stdlib.h>
int main() {
int desc[2], status, pid, n,n_lus;
int taille=3;
char chaine[taille+1];
pipe(desc);
pid=fork();
if(pid==0) {// lecteur
close (desc[1]);
while((n_lus=read (desc[0], &chaine, taille))){
Exemple :
Lecture 3 caractères au plus
à chaque fois qu’il y a des
données à la sortie du tube
Tube anonyme :Application
while((n_lus=read (desc[0], &chaine, taille))){
chaine[n_lus]='0';
printf (" message reçue : %s n", chaine);
}
close (desc[0]);
}else {// Ecrivain
close (desc[0]);
n=write (desc[1], "bonjour", 7);
close (desc[1]);
wait(&status);
}
return 0;
}
15
Ou
}else {// Ecrivain
close (desc[0]);
char buf[14];
fgets(buf,sizeof(buf),stdin); //donnée s à partir
du clavier
//printf("len=%d n",(int) strlen(buf));
n_lus=write (desc[1], buf, (int) strlen(buf));
close (desc[1]);
wait(&status);
}
Exercice 1 :
Ecrire un programme utilisant un tube anonyme permettant au père
de saisir un entier, le transmettre au fils. Le fils calcule son double et
l’affiche .
Tube anonyme :Application
16
int main(){
pid_t pid_fils;
int status, p1;
int desc[2];
p1=pipe(desc);
pid_fils=fork();
if(pid_fils==-1){
printf(" erreur fork () n");
exit(1); }
if(pid_fils==0){
int n_lu,x; float res;
sleep(2);
#include <stdio.h>
#include <unistd.h>
#include<sys/types.h>
#include <stdlib.h>
#include<sys/wait.h>
#include <errno.h>
#include<math.h>
17
sleep(2);
close(desc[1]);
n_lu=read(desc[0],&x,sizeof(float);
close(desc[0]);
printf("double = %d n",2*x);
}else{
int n_ec; int x;
close(desc[0]);
printf("saisir x: n");
scanf("%d",&x);
n_ec=write(desc[1],&x,sizeof(int); close(desc[]);
waitpid(pid_fils,&status, 0);
} return 0; }
Communication bidirectionnelle
Exercice :
Ecrire un programme permettant à un père d’envoyer un message
« bonjour fils» au fils et le fils répond par « bonjour père ».
Tube anonyme : Application
18
int main(){
pid_t pid_fils;
int status, p1,p2, desc[2],desc1[2];
p1=pipe(desc);
p2=pipe(desc1);
pid_fils=fork();
if(pid_fils==0){ //le fils
int n_lu;
#include <stdio.h>
#include <unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/wait.h>
# include <string.h>
Communication bidirectionnelle
Une solution :
}else{
int n_ec;
char buffw[20], buffR[100];
close(desc[0]);
close (desc1[1]);
int n_lu;
char buff[20];
close(desc[1]);
close(desc1[0]);
// lecture du message par le fils
n_lu=read(desc[0],buff,sizeof(buff));
printf("message du pere : %s n",buff);
//Le fils repond
printf("fils saisir : n");
fgets(buff,13,stdin);
write(desc1[1], buff, strlen(buff));
close(desc[0]); close(desc1[1]);
19
close (desc1[1]);
printf("saisir un message : n");
fgets(buffw,13,stdin);
// envoi d’un message au fils
n_ec=write(desc[1],buffw, strlen(buffw));
// lecture de la réponse du fils
read(desc1[0],buffR,sizeof(buffR));
close(desc[1]); close(desc1[0]);
wait(&status);
}
return 0;
}
int main() {
int desc1[2], desc2[2], status, pid,n;
char mesg[13], rep[13];
pipe(desc1);
pipe(desc2);
pid=fork();
if(pid==0) {
close (desc1[1]);
else {
close (desc1[0]);
close (pip2[1]);
write (desc1[1], "bonjour fils", 12);
close(desc1[1]);
read (desc2[0], rep, sizeof(rep));
close (desc2[0]);
printf ("reponse reçue par le père : %s", rep);
exit(0);
}
Communication bidirectionnelle
Une solution :
close (desc1[1]);
close (desc2[0]);
n=read (desc1[0], mesg, sizeof(mesg));
close(desc1[0]);
printf ("message recue par le fils : %s", mesg);
write (desc2[1], "bonjour pere", 12);
close (desc2[1]);
exit(0);
}
}
return 0;
}
20
Exercice 3:
Ecrire un programme permettant au père de saisir un ensemble d’entiers et de les
transmettre au fils. Le fils calcul la moyenne et l’affiche
Améliorer le programme précédent pour permettre au fils de transmettre la
moyenne calculée, précédemment, au père puis le père l’affiche.
Tube anonyme : Application
21
21
moyenne calculée, précédemment, au père puis le père l’affiche.
●Objectif :
Les redirections ont pour effet de rediriger un flux vers un autre flux, typiquement
les flux standards d'entrée/sortie : stdin, stdout et stderr.
● Mise en œuvre en utilisant les primitives : dup2, dup
Les appels dup et dup2 permettent de dupliquer des entrées de la table des
descripteurs du processus
● dup :
#include <unistd.h>
Redirection
#include <unistd.h>
int dup(int desc1);
recopie dans la première entrée libre du tableau des descripteurs l’entrée
correspondante au descripteur desc1.
22
● dup2 :
#include <unistd.h>
int dup2(int fd1, int fd2);
== > fd1 et fd2 désignent le même fichier, c’est le fichier désigné par fd1 avant l'appel.
Si fd2 désigne le descripteur d’un fichier ouvert, celui-ci est préalablement fermé (close(fd2))
avant duplication.
Rediriger les flots d’entrées-sorties vers
des tubes
Un usage pratique :
● Possibilité de lier la sortie tube[0] du tube à l’entrée standard (stdin). Par la
suite, tout ce qui sort du tube arrive sur le flot d’entrée standard
Pour se faire :
dup2(tube[0], STDIN_FILENO);
Ou
dup2(tube[0], 0);
● Idem lier l’entrée du tube avec la
sortie standard :
dup2(tube[1], STDOUT_FILENO);
ou
dup2(tube[1], 1);
23
Exemple le père est le lecteur :
(1) pipe(desc);
(2) fork( );
(3) close(desc[1]);
(4) dup2(desc[0], STDIN_FILENO);
Pour l’écrivain (un fils):
(3) close(desc[0]);
(4) dup2(desc[1], STDOUT_FILENO);
(5) close(desc[1]);
 redirige la sortie stdout vers l’entrée du
tube
Rediriger les flots d’entrées-sorties vers
des tubes
24
24
(4) dup2(desc[0], STDIN_FILENO);
(5) close(desc[0]);
 Lecture de Stdin:
Redirection de la sortie du tube vers
sdtin : on obtient donc les caractères
écrits par le processus-fils dans stdout
tube
24
Table de descripteurs du
processus fils
Table de descripteurs du
processus père
Application :
cat file | wc –l
Rediriger les flots d’entrées-sorties vers
des tubes
25
close (desc[0]);
dup2(desc[1],STDOUT_FILENO);
close (desc[1]);
execl ("/bin/cat", "cat", "file1",NULL)
close (desc[1]);
dup2(desc[0],STDIN_FILENO);
close (desc [0]);
execlp ("wc", "wc", "-l", NULL)
cat file wc –l
int main (int argc, char ** argv) {
int tubeDesc[2]; pid_t pid_fils;
if (pipe (tubeDesc) == -1) {
perror ("pipe");
exit (1);
}
if ( (pid_fils = fork ( )) == -1 ){
perror ("fork");
exit (1);
}
if (pid_fils == 0) { /* fils */
else { /* pere*/
close (tubeDesc[1]);
dup2(tubeDesc[0],0);
if (execlp("wc","wc", "-l", NULL) == -1) {
exit (1);
}
}
return 0;
}
26
if (pid_fils == 0) { /* fils */
close (tubeDesc[0]);
dup2(tubeDesc[1],1);
char* file="file1";
if (execl("/bin/cat", "cat",file,NULL) == -1) {
//execl("/bin/cat", "cat", "clone1.c",NULL);
exit (1);
}
}
}
● Restriction des tubes anonyme :
fonctionnement avec des processus issus d’un ancêtre commun
● Principal avantage :
Les mécanismes de communication mis en jeu dans le noyau sont généraux.
● Pour s’affranchir de la restriction :
les processus doivent désigner le tube qu’ils souhaitent utiliser.
== > utilisation du système de fichiers :
Un tube nommé
27
Tube nommé
28
● On peut faire communiquer deux processus à travers un tube nommé.
● Géré par le système de fichiers :
Un tube nommé correspond à un fichier avec un nom. Il passe donc par un
fichier sur le disque
● Intérêt :
les deux processus n’ont plus besoin d’avoir un lien de parenté
Tube nommé
29
● Etapes :
- Création : mkfifo()
- Ouverture : open()
- Lecture / écriture : read() et write()
- Fermeture : close()
- Destruction : unlink()
● Création d'un tube nommé avec commande shell :
mkfifo [-p] [-m mode] fileTube
-m mode : droits d'accès (même que chmod)
-p : création automatique de tous les répertoires intermédiaires dans le
chemin fileTube
Création d’un tube nommé
Exemple :
entrée sortie
écriture lecture
30
$> cat file2 >tube1
$> cat <tube1
affichage du contenu
de file2
écriture
lecture
Exemple :
Création d’un tube nommé
● Appel système de création : mkfifo
Exemple :
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo (const char *nom, mode_t mode);
- nom : nom du tube nommé
- mode: correspond aux droits d’accès associés au tube
31
Exemple :
Créez un tube nommé caractérisé par :
- propriétaire : possède toutes les permissions,
- le groupe : les droits de lecture et d'écriture
- les autres : aucun droits.
Solution 1 :
mkfifo("essai", S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP)
Solution 2 :
mkfifo("essai", 0760)
Exploitation :
solution 1 :
int f;
mode_t mode;
mode = S_IRUSR | S_IWUSR | S_IXUSR ;
f=mkfifo("essai", mode);
// f=mkfifo(("essai"), S_IRUSR | S_IWUSR | S_IXUSR );
if (f== -1){printf("Erreur de création du tube");
Création d’un tube nommé
if (f== -1){printf("Erreur de création du tube");
exit(1);
}
ou:
int f;
f=mkfifo(("essai"), 0760);
if (f== -1){
printf(stderr, "Erreur de création du tube");
exit(1);
}
32
Ouverture d’un tube nommé
● Primitive :
int open (const char *nom, int mode_ouverture);
renvoie -1 si erreur, sinon une valeur de type int (!=-1) c’est la valeur du
descripteur que l'on attribue l'extrémité du tube en question. C’est le
descripteur correspondant au mode d’ouverture spécifié.
● Ensuite, il faut ouvrir l'entrée/la sortie du tube avec la fonction open :
descripteur correspondant au mode d’ouverture spécifié.
- Le premier argument est le nom du tube nommé
-Le second argument indique si c'est l'entrée ou la sortie du tube (mode d’ouverture).
- mode d’ouverture : Il existe deux constantes pour cela, déclarées dans fcntl.h :
O_WRONLY : pour l'entrée ;
O_RDONLY : pour la sortie.
33
Ensuite, on peut écrire et lire avec write et read comme si c'était des fichiers classiques.
● Ecrivain == > write :
Exemple : Pour ouvrir l’entrée d'un tube « essai » en écriture :
int desc1,n;
desc1 = open("essai", O_WRONLY);
n= write(desc1 , chaineAEcrire, TAILLE_Ecriture);
Ouverture et écriture
34
● Lecteur == > read :
Exemple : Pour ouvrir la sortie d'un tube « essai » en lecture :
int desc0,n_lus;
desc0 = open("essai", O_RDONLY);
n_lus= read(desc0 , chaineALires, TAILLE);
● Destruction : unlink(char *pipe_nomme)
unlink("essai");
Écrivez deux programmes indépendants : un écrit un message dans un tube nommé,
et l'autre le lit, puis l'affiche.
Exemple de communication avec tube nommé
35
Ecrivain : Ecrivain.c
(*)
int main(){
char buff[255];
char file[]="temp6";
int desc,it;
it=mkfifo(file,0755);
printf("it=%d n",it);
if(it==-1)
(*)
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include<string.h>
Exemple de communication avec tube nommé
if(it==-1)
{
printf(“erreurn");
exit(1);
}
printf("saisir n");
fgets(buff,255,stdin);
desc=open(file,O_WRONLY);
write(desc,buff,strlen(buff));
return 0;
}
36
Lecteur : lecteur.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include<string.h>
Exemple de communication avec tube nommé
int main(){
char buff[255];
char file[]="temp6";
int desc, n_lus;
desc=open(file,O_RDONLY);
while((n_lus= read(desc,buff,30))) printf("recu : %s",buff);
unlink(file);
return 0;
}
37

Contenu connexe

Tendances

2009 2010-l3-reseau-td2-adressage-routage ip-corrige
2009 2010-l3-reseau-td2-adressage-routage ip-corrige2009 2010-l3-reseau-td2-adressage-routage ip-corrige
2009 2010-l3-reseau-td2-adressage-routage ip-corrigeAbabacar Faye
 
Introduction_Reseau.ppt
Introduction_Reseau.pptIntroduction_Reseau.ppt
Introduction_Reseau.pptAmalHadri2
 
Composants et fonctionnement d'un Routeur Cisco
Composants et fonctionnement d'un Routeur CiscoComposants et fonctionnement d'un Routeur Cisco
Composants et fonctionnement d'un Routeur CiscoDJENNA AMIR
 
Les Topologies Physiques des réseaux informatiques
Les Topologies Physiques des réseaux informatiquesLes Topologies Physiques des réseaux informatiques
Les Topologies Physiques des réseaux informatiquesATPENSC-Group
 
Atelier Reseaux informatiques
Atelier Reseaux informatiquesAtelier Reseaux informatiques
Atelier Reseaux informatiquesfulgence
 
Correction TD Adressage IP.pdf
Correction  TD Adressage IP.pdfCorrection  TD Adressage IP.pdf
Correction TD Adressage IP.pdfssuser18776b
 
Formation python
Formation pythonFormation python
Formation pythonj_lipaz
 
Typologie des réseaux informatiques
Typologie des réseaux informatiquesTypologie des réseaux informatiques
Typologie des réseaux informatiquesATPENSC-Group
 
Exposé de SE Systemes distribués
Exposé de SE Systemes distribuésExposé de SE Systemes distribués
Exposé de SE Systemes distribuésYoussouf Saleh Gao
 
Chapitre iv entrées sorties et bus
Chapitre iv entrées sorties et busChapitre iv entrées sorties et bus
Chapitre iv entrées sorties et busSana Aroussi
 
Telecharger Cours Systèmes d’exploitation windows: Administration Windows
Telecharger Cours Systèmes d’exploitation windows: Administration  WindowsTelecharger Cours Systèmes d’exploitation windows: Administration  Windows
Telecharger Cours Systèmes d’exploitation windows: Administration Windowswebreaker
 
Architecture ordinateur-echange-de-donnees
Architecture ordinateur-echange-de-donneesArchitecture ordinateur-echange-de-donnees
Architecture ordinateur-echange-de-donneesAbdoulaye Dieng
 
Chapitre 2: Modèle de référence OSI
Chapitre 2: Modèle de référence OSIChapitre 2: Modèle de référence OSI
Chapitre 2: Modèle de référence OSIMohamed Lahby
 

Tendances (20)

2009 2010-l3-reseau-td2-adressage-routage ip-corrige
2009 2010-l3-reseau-td2-adressage-routage ip-corrige2009 2010-l3-reseau-td2-adressage-routage ip-corrige
2009 2010-l3-reseau-td2-adressage-routage ip-corrige
 
Le protocole stp
Le protocole stpLe protocole stp
Le protocole stp
 
Introduction_Reseau.ppt
Introduction_Reseau.pptIntroduction_Reseau.ppt
Introduction_Reseau.ppt
 
(protocoles)
(protocoles)(protocoles)
(protocoles)
 
Routage
RoutageRoutage
Routage
 
Composants et fonctionnement d'un Routeur Cisco
Composants et fonctionnement d'un Routeur CiscoComposants et fonctionnement d'un Routeur Cisco
Composants et fonctionnement d'un Routeur Cisco
 
Snmp
SnmpSnmp
Snmp
 
Les Topologies Physiques des réseaux informatiques
Les Topologies Physiques des réseaux informatiquesLes Topologies Physiques des réseaux informatiques
Les Topologies Physiques des réseaux informatiques
 
Le modèle OSI
Le modèle OSILe modèle OSI
Le modèle OSI
 
Atelier Reseaux informatiques
Atelier Reseaux informatiquesAtelier Reseaux informatiques
Atelier Reseaux informatiques
 
Correction TD Adressage IP.pdf
Correction  TD Adressage IP.pdfCorrection  TD Adressage IP.pdf
Correction TD Adressage IP.pdf
 
Formation python
Formation pythonFormation python
Formation python
 
Typologie des réseaux informatiques
Typologie des réseaux informatiquesTypologie des réseaux informatiques
Typologie des réseaux informatiques
 
Exposé de SE Systemes distribués
Exposé de SE Systemes distribuésExposé de SE Systemes distribués
Exposé de SE Systemes distribués
 
Chapitre iv entrées sorties et bus
Chapitre iv entrées sorties et busChapitre iv entrées sorties et bus
Chapitre iv entrées sorties et bus
 
Virtuals LAN
Virtuals LANVirtuals LAN
Virtuals LAN
 
Telecharger Cours Systèmes d’exploitation windows: Administration Windows
Telecharger Cours Systèmes d’exploitation windows: Administration  WindowsTelecharger Cours Systèmes d’exploitation windows: Administration  Windows
Telecharger Cours Systèmes d’exploitation windows: Administration Windows
 
IPv6
IPv6IPv6
IPv6
 
Architecture ordinateur-echange-de-donnees
Architecture ordinateur-echange-de-donneesArchitecture ordinateur-echange-de-donnees
Architecture ordinateur-echange-de-donnees
 
Chapitre 2: Modèle de référence OSI
Chapitre 2: Modèle de référence OSIChapitre 2: Modèle de référence OSI
Chapitre 2: Modèle de référence OSI
 

Similaire à Tubes.pdf

Similaire à Tubes.pdf (20)

Chap3 Communication Inter Processus.pptx
Chap3 Communication Inter Processus.pptxChap3 Communication Inter Processus.pptx
Chap3 Communication Inter Processus.pptx
 
05_ProgrammationSystemeLinux_Tubes.pdf
05_ProgrammationSystemeLinux_Tubes.pdf05_ProgrammationSystemeLinux_Tubes.pdf
05_ProgrammationSystemeLinux_Tubes.pdf
 
Gestion d'E_S - Sérialisation.pdf
Gestion d'E_S - Sérialisation.pdfGestion d'E_S - Sérialisation.pdf
Gestion d'E_S - Sérialisation.pdf
 
Cours Linux , bases de l'administration linux
Cours Linux , bases de l'administration linuxCours Linux , bases de l'administration linux
Cours Linux , bases de l'administration linux
 
Linux Administrateur
Linux AdministrateurLinux Administrateur
Linux Administrateur
 
Tp n 5 linux
Tp n 5 linuxTp n 5 linux
Tp n 5 linux
 
Processus pére fils
Processus pére filsProcessus pére fils
Processus pére fils
 
lpi 101 notes de cours
lpi 101 notes de courslpi 101 notes de cours
lpi 101 notes de cours
 
Chapitre 5 Linux
Chapitre 5 LinuxChapitre 5 Linux
Chapitre 5 Linux
 
UNIX_SE4_2023 (1).pdf
UNIX_SE4_2023 (1).pdfUNIX_SE4_2023 (1).pdf
UNIX_SE4_2023 (1).pdf
 
Formation python
Formation pythonFormation python
Formation python
 
Chapitre 4 Linux
Chapitre 4 LinuxChapitre 4 Linux
Chapitre 4 Linux
 
Langage C
Langage CLangage C
Langage C
 
Cours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdfCours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdf
 
system de gestion Nfs (Network File System)
system de gestion Nfs (Network File System)system de gestion Nfs (Network File System)
system de gestion Nfs (Network File System)
 
Rapport Projet Module Complexité
Rapport Projet Module ComplexitéRapport Projet Module Complexité
Rapport Projet Module Complexité
 
03_ProgrammationSystemeLinux_Thread.pdf
03_ProgrammationSystemeLinux_Thread.pdf03_ProgrammationSystemeLinux_Thread.pdf
03_ProgrammationSystemeLinux_Thread.pdf
 
Formation Informatique base et généralités
Formation Informatique base et généralitésFormation Informatique base et généralités
Formation Informatique base et généralités
 
Tp n 3 linux
Tp n 3 linuxTp n 3 linux
Tp n 3 linux
 
Expose linux gestion des processus
Expose linux  gestion des processusExpose linux  gestion des processus
Expose linux gestion des processus
 

Tubes.pdf

  • 2. - Les processus concurrents peuvent être : - coopératifs : dépendants les uns des autre - ou indépendants - Les processus peuvent coopérer : - par communication de données - ou en partageant des ressources (mémoire, …)  Besoin de communiquer entre processus pour échanger des données et informations,  Besoin de synchronisation .
  • 4. ● Il existe plusieurs moyens de communication entre processus : - Par le biais d’un fichier - tube - Signaux - Par une zone mémoire - Files de messages (MSQ) I- Communication entre processus - Files de messages (MSQ) 4
  • 5. I-1- Communication par tubes 5 ● Objectif de cette parties : permettre la communication entre processus.
  • 6. Communication par tubes ● Définition du tube (pipe) : Un tube est un fichier spécial géré par le système au niveau du système de gestion de fichiers. Il permet la communication entre deux processus de la manière suivante : un processus peut écrire des données dans le tube et un autre processus peut lire ces données. Processus écrivain : p1 Processus lecteur : P2 p2 6 ● Principe : deux extrémités (deux descripteurs) : une permettant d’´ecrire des données par le processus écrivain l’autre permettant de les lire par le processus lecteur ● On lit/écrit dans un tube comme on lit/écrit dans un fichier ordinaire
  • 7. ● Communication d’un flot continu de caractères - communication en mode flot (opposé à datagramme) : opérations de lecture indépendantes des opérations d’écriture ● Le fonctionnement est de type FIFO : - premier caractère écrit, premier caractère lu - Il n’est pas possible de lire un octet sans avoir lu tous ceux qui le précèdent ● Caractéristiques techniques : Communication par tubes ● Opération de lecture est destructive : une information lue est extraite du tube ● Si un tube est vide, ou si on a plus écrivains (extrémité d’écriture fermé) la lecture renvoie la valeur 0 (fin de fichier atteinte) ● Un processus qui écrit dans un tube qui n’a plus de lecteurs (extrémité de Lecture fermée ) reçoit le signal SIGPIPE ● Système assure la synchronisation entre le lecteur et l’écrivain : Bloque le processus lecteur quand le tube est vide. Bloque le processus ´écrivain quand le tube est plein 7
  • 8. ● Deux types de tubes : 1- Tubes anonymes 2- Tubes nommés Communication par tubes 8
  • 9. P1 (écrire) P2 (lire) Tubes anonymes ● Caractéristiques : ● Un tube annonyme est un fichier particulier : - Il n’a pas de nom dans l’arborescence des fichiers - Il est connu par deux descripteurs (lecture, écriture) ● Permet la communication entre processus qui ont un lien de parenté : les deux processus doivent connaitre le même canal afin de communiquer == > héritage du descripteur desc[1] desc[0] 9 == > héritage du descripteur ● temporaires (volatile) : ils n’existent que le temps d’exécution du processus qui les crée.
  • 10. ● Création : par appel systéme pipe, déclarée dans unistd.h ● Primitive : #include <unistd.h> int desc[2]; int pipe(int desc); Processus écrivain Processus lecteur Création de tubes anonymes retourne 0 si le tube est donc créé, -1 si en cas d’echec ► l'appel pipe retourne deux descripteurs : - desc[0] : Pour la lecture. C’est la sortie du tube dans laquelle on peut lire des données. Il doit être ouvert pour la lecture seule - desc[1] : Pour l’écriture. C’est l’entrée du tube dans laquelle on peut écrire des données. Il doit être ouvert pour l’écriture seule desc[1] desc[0] 10 ● Les descripteurs du tube doit être partagé par les processus communiquant == > l’appel pipe doit se faire avant fork() !!!
  • 11. desc[0] Création de tubes anonymes desc[1] 11
  • 12. ● Le tube doit être créé avant le fork pour que les descripteurs du tube soient hérités par les processus qui vont communiquer via le tube (héritage des descripteurs lors du fork() ) : Un tube est créé dans un seul processus. Le processus fils ne peut pas deviner les valeurs du tableau descripteur. Il faut donc appeler la fonction pipe avant d’appeler la fonction fork. Cela permet au processus père et le(s) processus fils (sa descendance) d’avoir les mêmes descripteurs de tubes, et pourront donc communiquer entre eux. Création de tubes anonymes et fork() communiquer entre eux. ● Rappelons qu’un tube ne permet de communiquer que dans un seul sens. Si l’on souhaite que les processus communiquent dans les deux sens, il faut créer deux pipes. 12
  • 13. Si le processus père écris, le processus fils lis : Partage d’un tube Processus lecteur (exemple : fils) hérite de desc[1] et desc[0] desc[1] desc[0] Processus écrivain (exemple : père) desc[1] desc[0] close(desc[0]) close(desc[1]) 1) pipe() 2) fork() 13 int close(int desc); == > - close(desc[1]) dans le processus lecteur - close(desc[0]) dans le processus écrivain tube Extrémité d’écriture Extrémité de lecture ● Il faut fermer le descripteur inutile dans chaque processus : primitive close -- > sinon interblocage close(desc[0]) close(desc[1])
  • 14. Ecriture/lecture dans un tube anonyme ● Pour écrire dans un tube : write ● Un tube à une capacité max : notée PIPE_BUF. C’est la taille du tube sur le système == > <limits.h> ● le signal SIGPIPE est envoyé au processus qui exécute write si le tube n’a ● Primitive : int write(int desc[1], const void *bufW, int nb_ecris); - nb_ecris : nombre d’octet à écrire - bufW : pointeur générique vers la mémoire contenant les données à écrire - l’appel retourne en résultat le nombre d’octets écris ● le signal SIGPIPE est envoyé au processus qui exécute write si le tube n’a été ouvert en lecture par aucun autre processus (pas de lecteur). Ce signale termine le processus. 14 ● La lecture : read ● Primitive : int read(desc[0], char *buffR, int taille_lecture); - BufR : pointeur vers la mémoire contenant les données à lire - taille_lecture : le nombre d’octets qu’on souhaite lire depuis la sortie du tube desc [0] à partir du tampon bufR
  • 15. # include <stdio.h> # include<sys/wait.h> # include<unistd.h> # include <stdlib.h> int main() { int desc[2], status, pid, n,n_lus; int taille=3; char chaine[taille+1]; pipe(desc); pid=fork(); if(pid==0) {// lecteur close (desc[1]); while((n_lus=read (desc[0], &chaine, taille))){ Exemple : Lecture 3 caractères au plus à chaque fois qu’il y a des données à la sortie du tube Tube anonyme :Application while((n_lus=read (desc[0], &chaine, taille))){ chaine[n_lus]='0'; printf (" message reçue : %s n", chaine); } close (desc[0]); }else {// Ecrivain close (desc[0]); n=write (desc[1], "bonjour", 7); close (desc[1]); wait(&status); } return 0; } 15 Ou }else {// Ecrivain close (desc[0]); char buf[14]; fgets(buf,sizeof(buf),stdin); //donnée s à partir du clavier //printf("len=%d n",(int) strlen(buf)); n_lus=write (desc[1], buf, (int) strlen(buf)); close (desc[1]); wait(&status); }
  • 16. Exercice 1 : Ecrire un programme utilisant un tube anonyme permettant au père de saisir un entier, le transmettre au fils. Le fils calcule son double et l’affiche . Tube anonyme :Application 16
  • 17. int main(){ pid_t pid_fils; int status, p1; int desc[2]; p1=pipe(desc); pid_fils=fork(); if(pid_fils==-1){ printf(" erreur fork () n"); exit(1); } if(pid_fils==0){ int n_lu,x; float res; sleep(2); #include <stdio.h> #include <unistd.h> #include<sys/types.h> #include <stdlib.h> #include<sys/wait.h> #include <errno.h> #include<math.h> 17 sleep(2); close(desc[1]); n_lu=read(desc[0],&x,sizeof(float); close(desc[0]); printf("double = %d n",2*x); }else{ int n_ec; int x; close(desc[0]); printf("saisir x: n"); scanf("%d",&x); n_ec=write(desc[1],&x,sizeof(int); close(desc[]); waitpid(pid_fils,&status, 0); } return 0; }
  • 18. Communication bidirectionnelle Exercice : Ecrire un programme permettant à un père d’envoyer un message « bonjour fils» au fils et le fils répond par « bonjour père ». Tube anonyme : Application 18
  • 19. int main(){ pid_t pid_fils; int status, p1,p2, desc[2],desc1[2]; p1=pipe(desc); p2=pipe(desc1); pid_fils=fork(); if(pid_fils==0){ //le fils int n_lu; #include <stdio.h> #include <unistd.h> #include<sys/types.h> #include<stdlib.h> #include<sys/wait.h> # include <string.h> Communication bidirectionnelle Une solution : }else{ int n_ec; char buffw[20], buffR[100]; close(desc[0]); close (desc1[1]); int n_lu; char buff[20]; close(desc[1]); close(desc1[0]); // lecture du message par le fils n_lu=read(desc[0],buff,sizeof(buff)); printf("message du pere : %s n",buff); //Le fils repond printf("fils saisir : n"); fgets(buff,13,stdin); write(desc1[1], buff, strlen(buff)); close(desc[0]); close(desc1[1]); 19 close (desc1[1]); printf("saisir un message : n"); fgets(buffw,13,stdin); // envoi d’un message au fils n_ec=write(desc[1],buffw, strlen(buffw)); // lecture de la réponse du fils read(desc1[0],buffR,sizeof(buffR)); close(desc[1]); close(desc1[0]); wait(&status); } return 0; }
  • 20. int main() { int desc1[2], desc2[2], status, pid,n; char mesg[13], rep[13]; pipe(desc1); pipe(desc2); pid=fork(); if(pid==0) { close (desc1[1]); else { close (desc1[0]); close (pip2[1]); write (desc1[1], "bonjour fils", 12); close(desc1[1]); read (desc2[0], rep, sizeof(rep)); close (desc2[0]); printf ("reponse reçue par le père : %s", rep); exit(0); } Communication bidirectionnelle Une solution : close (desc1[1]); close (desc2[0]); n=read (desc1[0], mesg, sizeof(mesg)); close(desc1[0]); printf ("message recue par le fils : %s", mesg); write (desc2[1], "bonjour pere", 12); close (desc2[1]); exit(0); } } return 0; } 20
  • 21. Exercice 3: Ecrire un programme permettant au père de saisir un ensemble d’entiers et de les transmettre au fils. Le fils calcul la moyenne et l’affiche Améliorer le programme précédent pour permettre au fils de transmettre la moyenne calculée, précédemment, au père puis le père l’affiche. Tube anonyme : Application 21 21 moyenne calculée, précédemment, au père puis le père l’affiche.
  • 22. ●Objectif : Les redirections ont pour effet de rediriger un flux vers un autre flux, typiquement les flux standards d'entrée/sortie : stdin, stdout et stderr. ● Mise en œuvre en utilisant les primitives : dup2, dup Les appels dup et dup2 permettent de dupliquer des entrées de la table des descripteurs du processus ● dup : #include <unistd.h> Redirection #include <unistd.h> int dup(int desc1); recopie dans la première entrée libre du tableau des descripteurs l’entrée correspondante au descripteur desc1. 22 ● dup2 : #include <unistd.h> int dup2(int fd1, int fd2); == > fd1 et fd2 désignent le même fichier, c’est le fichier désigné par fd1 avant l'appel. Si fd2 désigne le descripteur d’un fichier ouvert, celui-ci est préalablement fermé (close(fd2)) avant duplication.
  • 23. Rediriger les flots d’entrées-sorties vers des tubes Un usage pratique : ● Possibilité de lier la sortie tube[0] du tube à l’entrée standard (stdin). Par la suite, tout ce qui sort du tube arrive sur le flot d’entrée standard Pour se faire : dup2(tube[0], STDIN_FILENO); Ou dup2(tube[0], 0); ● Idem lier l’entrée du tube avec la sortie standard : dup2(tube[1], STDOUT_FILENO); ou dup2(tube[1], 1); 23
  • 24. Exemple le père est le lecteur : (1) pipe(desc); (2) fork( ); (3) close(desc[1]); (4) dup2(desc[0], STDIN_FILENO); Pour l’écrivain (un fils): (3) close(desc[0]); (4) dup2(desc[1], STDOUT_FILENO); (5) close(desc[1]);  redirige la sortie stdout vers l’entrée du tube Rediriger les flots d’entrées-sorties vers des tubes 24 24 (4) dup2(desc[0], STDIN_FILENO); (5) close(desc[0]);  Lecture de Stdin: Redirection de la sortie du tube vers sdtin : on obtient donc les caractères écrits par le processus-fils dans stdout tube 24
  • 25. Table de descripteurs du processus fils Table de descripteurs du processus père Application : cat file | wc –l Rediriger les flots d’entrées-sorties vers des tubes 25 close (desc[0]); dup2(desc[1],STDOUT_FILENO); close (desc[1]); execl ("/bin/cat", "cat", "file1",NULL) close (desc[1]); dup2(desc[0],STDIN_FILENO); close (desc [0]); execlp ("wc", "wc", "-l", NULL) cat file wc –l
  • 26. int main (int argc, char ** argv) { int tubeDesc[2]; pid_t pid_fils; if (pipe (tubeDesc) == -1) { perror ("pipe"); exit (1); } if ( (pid_fils = fork ( )) == -1 ){ perror ("fork"); exit (1); } if (pid_fils == 0) { /* fils */ else { /* pere*/ close (tubeDesc[1]); dup2(tubeDesc[0],0); if (execlp("wc","wc", "-l", NULL) == -1) { exit (1); } } return 0; } 26 if (pid_fils == 0) { /* fils */ close (tubeDesc[0]); dup2(tubeDesc[1],1); char* file="file1"; if (execl("/bin/cat", "cat",file,NULL) == -1) { //execl("/bin/cat", "cat", "clone1.c",NULL); exit (1); } } }
  • 27. ● Restriction des tubes anonyme : fonctionnement avec des processus issus d’un ancêtre commun ● Principal avantage : Les mécanismes de communication mis en jeu dans le noyau sont généraux. ● Pour s’affranchir de la restriction : les processus doivent désigner le tube qu’ils souhaitent utiliser. == > utilisation du système de fichiers : Un tube nommé 27
  • 29. ● On peut faire communiquer deux processus à travers un tube nommé. ● Géré par le système de fichiers : Un tube nommé correspond à un fichier avec un nom. Il passe donc par un fichier sur le disque ● Intérêt : les deux processus n’ont plus besoin d’avoir un lien de parenté Tube nommé 29 ● Etapes : - Création : mkfifo() - Ouverture : open() - Lecture / écriture : read() et write() - Fermeture : close() - Destruction : unlink()
  • 30. ● Création d'un tube nommé avec commande shell : mkfifo [-p] [-m mode] fileTube -m mode : droits d'accès (même que chmod) -p : création automatique de tous les répertoires intermédiaires dans le chemin fileTube Création d’un tube nommé Exemple : entrée sortie écriture lecture 30 $> cat file2 >tube1 $> cat <tube1 affichage du contenu de file2 écriture lecture Exemple :
  • 31. Création d’un tube nommé ● Appel système de création : mkfifo Exemple : #include <sys/types.h> #include <sys/stat.h> int mkfifo (const char *nom, mode_t mode); - nom : nom du tube nommé - mode: correspond aux droits d’accès associés au tube 31 Exemple : Créez un tube nommé caractérisé par : - propriétaire : possède toutes les permissions, - le groupe : les droits de lecture et d'écriture - les autres : aucun droits. Solution 1 : mkfifo("essai", S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP) Solution 2 : mkfifo("essai", 0760)
  • 32. Exploitation : solution 1 : int f; mode_t mode; mode = S_IRUSR | S_IWUSR | S_IXUSR ; f=mkfifo("essai", mode); // f=mkfifo(("essai"), S_IRUSR | S_IWUSR | S_IXUSR ); if (f== -1){printf("Erreur de création du tube"); Création d’un tube nommé if (f== -1){printf("Erreur de création du tube"); exit(1); } ou: int f; f=mkfifo(("essai"), 0760); if (f== -1){ printf(stderr, "Erreur de création du tube"); exit(1); } 32
  • 33. Ouverture d’un tube nommé ● Primitive : int open (const char *nom, int mode_ouverture); renvoie -1 si erreur, sinon une valeur de type int (!=-1) c’est la valeur du descripteur que l'on attribue l'extrémité du tube en question. C’est le descripteur correspondant au mode d’ouverture spécifié. ● Ensuite, il faut ouvrir l'entrée/la sortie du tube avec la fonction open : descripteur correspondant au mode d’ouverture spécifié. - Le premier argument est le nom du tube nommé -Le second argument indique si c'est l'entrée ou la sortie du tube (mode d’ouverture). - mode d’ouverture : Il existe deux constantes pour cela, déclarées dans fcntl.h : O_WRONLY : pour l'entrée ; O_RDONLY : pour la sortie. 33
  • 34. Ensuite, on peut écrire et lire avec write et read comme si c'était des fichiers classiques. ● Ecrivain == > write : Exemple : Pour ouvrir l’entrée d'un tube « essai » en écriture : int desc1,n; desc1 = open("essai", O_WRONLY); n= write(desc1 , chaineAEcrire, TAILLE_Ecriture); Ouverture et écriture 34 ● Lecteur == > read : Exemple : Pour ouvrir la sortie d'un tube « essai » en lecture : int desc0,n_lus; desc0 = open("essai", O_RDONLY); n_lus= read(desc0 , chaineALires, TAILLE); ● Destruction : unlink(char *pipe_nomme) unlink("essai");
  • 35. Écrivez deux programmes indépendants : un écrit un message dans un tube nommé, et l'autre le lit, puis l'affiche. Exemple de communication avec tube nommé 35
  • 36. Ecrivain : Ecrivain.c (*) int main(){ char buff[255]; char file[]="temp6"; int desc,it; it=mkfifo(file,0755); printf("it=%d n",it); if(it==-1) (*) #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include<string.h> Exemple de communication avec tube nommé if(it==-1) { printf(“erreurn"); exit(1); } printf("saisir n"); fgets(buff,255,stdin); desc=open(file,O_WRONLY); write(desc,buff,strlen(buff)); return 0; } 36
  • 37. Lecteur : lecteur.c #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include<string.h> Exemple de communication avec tube nommé int main(){ char buff[255]; char file[]="temp6"; int desc, n_lus; desc=open(file,O_RDONLY); while((n_lus= read(desc,buff,30))) printf("recu : %s",buff); unlink(file); return 0; } 37