SlideShare une entreprise Scribd logo
1  sur  37
Télécharger pour lire hors ligne
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

Cours linux complet
Cours linux completCours linux complet
Cours linux completaubin82
 
Cours cryptographie Master 1
Cours cryptographie Master 1Cours cryptographie Master 1
Cours cryptographie Master 1Papis NIANG
 
Gestion des utilisateurs et groupes / Users & groups management
Gestion des utilisateurs et groupes / Users & groups managementGestion des utilisateurs et groupes / Users & groups management
Gestion des utilisateurs et groupes / Users & groups managementABDELLAH EL MAMOUN
 
Systèmes d'Exploitation - chp1-introduction
Systèmes d'Exploitation - chp1-introductionSystèmes d'Exploitation - chp1-introduction
Systèmes d'Exploitation - chp1-introductionLilia Sfaxi
 
Présentation des supports de stockage
Présentation des supports de stockagePrésentation des supports de stockage
Présentation des supports de stockageJamel Eddine Zarga
 
Cours python avancé
Cours python avancéCours python avancé
Cours python avancépierrepo
 
Support du cours : Systèmes d'exploitation 2 (linux)
Support du cours : Systèmes d'exploitation 2 (linux)Support du cours : Systèmes d'exploitation 2 (linux)
Support du cours : Systèmes d'exploitation 2 (linux)Faycel Chaoua
 
gestion de processus
gestion de processusgestion de processus
gestion de processusMoodyBop
 
Programmation Dynamique : Mise en œuvre et application à des problèmes en TAL
Programmation Dynamique : Mise en œuvre et application à des problèmes en TALProgrammation Dynamique : Mise en œuvre et application à des problèmes en TAL
Programmation Dynamique : Mise en œuvre et application à des problèmes en TALECAM Brussels Engineering School
 
Systèmes d'Exploitation - chp2-gestion des processus
Systèmes d'Exploitation - chp2-gestion des processusSystèmes d'Exploitation - chp2-gestion des processus
Systèmes d'Exploitation - chp2-gestion des processusLilia Sfaxi
 

Tendances (20)

Cours linux complet
Cours linux completCours linux complet
Cours linux complet
 
Cours cryptographie Master 1
Cours cryptographie Master 1Cours cryptographie Master 1
Cours cryptographie Master 1
 
Gestion des utilisateurs et groupes / Users & groups management
Gestion des utilisateurs et groupes / Users & groups managementGestion des utilisateurs et groupes / Users & groups management
Gestion des utilisateurs et groupes / Users & groups management
 
Cours de c
Cours de cCours de c
Cours de c
 
Hdlc
HdlcHdlc
Hdlc
 
Tp n 4 linux
Tp n 4 linuxTp n 4 linux
Tp n 4 linux
 
Systèmes d'Exploitation - chp1-introduction
Systèmes d'Exploitation - chp1-introductionSystèmes d'Exploitation - chp1-introduction
Systèmes d'Exploitation - chp1-introduction
 
Présentation des supports de stockage
Présentation des supports de stockagePrésentation des supports de stockage
Présentation des supports de stockage
 
Les reseaux
Les reseauxLes reseaux
Les reseaux
 
Tp n 5 linux
Tp n 5 linuxTp n 5 linux
Tp n 5 linux
 
Cours SNMP
Cours SNMPCours SNMP
Cours SNMP
 
Cours python avancé
Cours python avancéCours python avancé
Cours python avancé
 
Présentation Cryptographie
Présentation CryptographiePrésentation Cryptographie
Présentation Cryptographie
 
VoIP
VoIPVoIP
VoIP
 
Programmation en C
Programmation en CProgrammation en C
Programmation en C
 
Support du cours : Systèmes d'exploitation 2 (linux)
Support du cours : Systèmes d'exploitation 2 (linux)Support du cours : Systèmes d'exploitation 2 (linux)
Support du cours : Systèmes d'exploitation 2 (linux)
 
gestion de processus
gestion de processusgestion de processus
gestion de processus
 
Tp n 1 linux
Tp n 1 linuxTp n 1 linux
Tp n 1 linux
 
Programmation Dynamique : Mise en œuvre et application à des problèmes en TAL
Programmation Dynamique : Mise en œuvre et application à des problèmes en TALProgrammation Dynamique : Mise en œuvre et application à des problèmes en TAL
Programmation Dynamique : Mise en œuvre et application à des problèmes en TAL
 
Systèmes d'Exploitation - chp2-gestion des processus
Systèmes d'Exploitation - chp2-gestion des processusSystèmes d'Exploitation - chp2-gestion des processus
Systèmes d'Exploitation - chp2-gestion des processus
 

Similaire à Tubes.pdf

Chap3 Communication Inter Processus.pptx
Chap3 Communication Inter Processus.pptxChap3 Communication Inter Processus.pptx
Chap3 Communication Inter Processus.pptxZohraQassimi
 
05_ProgrammationSystemeLinux_Tubes.pdf
05_ProgrammationSystemeLinux_Tubes.pdf05_ProgrammationSystemeLinux_Tubes.pdf
05_ProgrammationSystemeLinux_Tubes.pdfLarbaSAWADOGO2
 
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.pdfMadaniAhlem2
 
Formation python
Formation pythonFormation python
Formation pythonj_lipaz
 
Processus pére fils
Processus pére filsProcessus pére fils
Processus pére filsSelman Dridi
 
lpi 101 notes de cours
lpi 101 notes de courslpi 101 notes de cours
lpi 101 notes de coursISIG
 
UNIX_SE4_2023 (1).pdf
UNIX_SE4_2023 (1).pdfUNIX_SE4_2023 (1).pdf
UNIX_SE4_2023 (1).pdfYassineZouin
 
Cours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdfCours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdfHailisara
 
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)ninanoursan
 
03_ProgrammationSystemeLinux_Thread.pdf
03_ProgrammationSystemeLinux_Thread.pdf03_ProgrammationSystemeLinux_Thread.pdf
03_ProgrammationSystemeLinux_Thread.pdfLarbaSAWADOGO2
 
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ésSinovatia
 
Manipulation des fichiers en C.pptx
Manipulation des fichiers en C.pptxManipulation des fichiers en C.pptx
Manipulation des fichiers en C.pptxolfaharrabi2
 
0079-cours-linux-base.ppt
0079-cours-linux-base.ppt0079-cours-linux-base.ppt
0079-cours-linux-base.pptAugustoMoundoh1
 
0079-cours-linux-base.ppt
0079-cours-linux-base.ppt0079-cours-linux-base.ppt
0079-cours-linux-base.pptMahdiHERMASSI1
 

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
 
Linux Administrateur
Linux AdministrateurLinux Administrateur
Linux Administrateur
 
Formation python
Formation pythonFormation python
Formation python
 
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
 
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
 
Manipulation des fichiers en C.pptx
Manipulation des fichiers en C.pptxManipulation des fichiers en C.pptx
Manipulation des fichiers en C.pptx
 
0079-cours-linux-base.ppt
0079-cours-linux-base.ppt0079-cours-linux-base.ppt
0079-cours-linux-base.ppt
 
0079-cours-linux-base.ppt
0079-cours-linux-base.ppt0079-cours-linux-base.ppt
0079-cours-linux-base.ppt
 

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