Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Unamed Pipes

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 21

Programmation Système sous

UNIX

Chapitre 3 : La communication
interprocessus avec des tubes

Najar Yousra
Email : yousra.najar@isi.utm.tn

ISI 2 éme ingérieur 2020/2021


Programmation Système sous UNIX
2 éme ing 76
Plan du chapitre
 Introduction
 Rappels sur les fonctions des E/S
 Les Tubes sans noms
 Les tubes nommés

Programmation Système sous UNIX


2 éme ing 77
Introduction
 Les tubes de communication ou pipes permettent à deux ou
plusieurs processus d’échanger des informations. On distingue
deux types de tubes : les tubes sans nom (unamed pipe ) et les
tubes nommés (named pipe ).
 Les données sont envoyées directement en mémoire sans être
stockées temporairement sur disque, ce qui est donc très rapide.

 Un tuyau de données a deux côtés : un côté permettant d’écrire


des données dedans et un côté permettant de les lire. Chaque côté
du tuyau est un descripteur de fichier ouvert soit en lecture soit en
écriture, ce qui permet de s’en servir très facilement, au moyen des
fonctions d’entrée / sortie classiques.

Programmation Système sous UNIX


2 éme ing 78
Rappels sur les entrées / Sorties
 Un descripteur de fichier se présente pour l’utilisateur sous
la forme d’un simple entier : le système d’exploitation tient
en fait à jour pour chaque processus une table, appelée table
des fichiers ouverts, où sont référencés tous les fichiers
utilisés, c’est-à-dire tous les fichiers en train d’être manipulés
par un processus (création, écriture, lecture), et l’entier mis à
disposition de l’utilisateur correspond au numéro de la ligne
de la table faisant référence au fichier concerné.
 Le mot fichier ne doit pas être compris ici au sens « fichier
sur le disque dur », mais comme une entité pouvant contenir
ou transmettre des données. Un descripteur de fichier peut
aussi bien faire référence à un fichier du disque dur, à un
terminal, à une connexion réseau ou à un lecteur de bande
magnétique.
Programmation Système sous UNIX
2 éme ing 79
Rappels sur les entrées / Sorties

Descripteurs spéciaux
Les descripteurs de fichier 0, 1 et 2 sont spéciaux : ils
représentent respectivement l’entrée standard, la
sortie standard et la sortie d’erreur. Si le programme
est lancé depuis un terminal de commande sans
redirection, 0 est associé au clavier, 1 et 2 à l’écran.
Ces descripteurs sont définis de manière plus lisible
dans le fichier <unistd.h> :
Programmation Système sous UNIX
2 éme ing 80
Rappels sur les entrées / Sorties
Appel système open
L’appel système open() permet d’associer un descripteur de fichier à un fichier que
l’on souhaite manipuler. En cas de succès, le système d’exploitation va créer une
référence dans la table des fichiers et va indiquer l’entier correspondant. Une fois
référencé dans la table des fichiers, le fichier est dit « ouvert ». L’appel système
open() s’utilise de la manière suivante :

#include <sys/types.h>
#include <sys/stat.h>
int open(const char *filename, int flags);
// Exemples:
open(”fifo”, O_RDONLY); // ouverture en lecture seule
open(”fifo”, O_WRONLY); // ouverture en écriture seule
open(”fifo”, O_RDONLY|O_NONBLOCK);
open(”fifo”, O_WRONLY|O_NONBLOCK);

Programmation Système sous UNIX


2 éme ing 81
Rappels sur les entrées / Sorties
Appel système read

Le paramètre fd indique le descripteur de fichier concerné, c’est-à-dire le fichier


dans lequel les données vont être lues. Le paramètre buf désigne une zone mémoire
dans laquelle les données lues vont être stockées. Cette zone mémoire doit être au
préalable allouée soit de façon statique (via un tableau par exemple), soit de façon
dynamique (via un appel à la fonction malloc() par exemple). Le paramètre nbytes
indique le nombre d’octets (et non le nombre de données) que l’appel read() va
essayer de lire (il se peut qu’il y ait moins de données que le nombre spécifié par
nbytes).
La valeur retournée par read() est le nombre d’octets effectivement lus. À la fin du
fichier (c’est-à-dire quand il n’y a plus de données disponibles), 0 est retourné. En cas
d’erreur, -1 est retourné.

Programmation Système sous UNIX


2 éme ing 82
Rappels sur les entrées / Sorties
Appel système write

L’appel système write() permet d’écrire des données dans un fichier représenté par
le descripteur de fichier fd. Il s’utilise de la même façon que l’appel système read().
La valeur retournée est le nombre d’octets effectivement écrits. En cas d’erreur, -1
est retourné.

Appel système de close

Cet appel permet de fermer un fichier précédemment ouvert par l’appel système
open(), c’est-à-dire de supprimer la référence à ce fichier dans la table maintenue par
le système (table des fichiers ouverts).

Appel système de duplication


int dup (int oldfd);
int dup2(int oldfd, int newfd);

L’appel système dup() permet d’associer à un même fichier plusieurs descripteurs.


dup() associe le plus petit descripteur libre au fichier pointé Système
Programmation par lesous
descripteur
UNIX oldfd.
2 éme ing 83
L’appel système dup2() associe le descripteur newfd au fichier pointé par oldfd.
Les tubes sans noms
Exemple :

Descripteurs de fichiers
ouverts
0 (entrée standard)

1 (sortie standard)

dup2(fd[1],6) 2 (sortie d’erreur )

3 (descripteur d’écriture f1)

4=fd[0] (lecture tube)

5=fd[1] ( écriture tube)

6 (écriture tube)
Programmation Système sous UNIX
2 éme ing 84
Les notions de base sur les tubes
I. La lecture d’un tuyau est bloquante, c’est-à-dire que si aucune donnée n’est
disponible en lecture, le processus essayant de lire le tuyau sera suspendu (il ne
sera pas pris en compte par l’ordonnanceur et n’occupera donc pas inutilement
le processeur) jusqu’à ce que des données soient disponibles. L’utilisation de
cette caractéristique comme effet de bord peut servir à synchroniser des
processus entre eux (les processus lecteurs étant synchronisés sur les processus
écrivains).

II. La lecture d’un tuyau est destructrice, c’est-à-dire que si plusieurs processus lisent le
même tuyau, toute donnée lue par l’un disparaît pour les autres. Par exemple, si un
processus écrit les deux caractères ab dans un tuyau lu par les processus A et B et
que A lit un caractère dans le tuyau, il lira le caractère a qui disparaîtra
immédiatement du tuyau sans que B puisse le lire. Si B lit alors un caractère dans le
tuyau, il lira donc le caractère b que A, à son tour, ne pourra plus y lire. Si l’on veut
donc envoyer des informations identiques à plusieurs processus, il est nécessaire de
créer un tuyau vers chacun d’eux.

III. De même qu’un tuyau en cuivre a une longueur finie, un tuyau de données à une
capacité finie. Un processus essayant d’écrire dansProgrammation
un tuyau Système
plein sous
se verra
UNIX suspendu
en attendant qu’un espace suffisant se libère 2 éme ing 85
Les tubes sans noms
Les tubes sans nom sont des liaisons unidirectionnelles de communication. La
taille maximale d’un tube sans nom varie d’une version à une autre d’Unix, mais
elle est approximativement égale à 5Ko. Les tubes sans nom peuvent être créés
par le shell ( | ) ou par l’appel système pipe().

L’argument de pipe() est un tableau de deux descripteurs de fichier (un descripteur


de fichier est du type int en C). Lorsque le tuyau a été créé, le premier descripteur,
tuyau[0], représente le côté lecture du tuyau et le second, tuyau[1], représente le
côté écriture.

RQ : L’accès au tube se fait via les descripteurs. Seul le processus créateur du tube
et ses descendants (ses fils) peuvent accéder au tube.

Programmation Système sous UNIX


2 éme ing 86
Les tubes sans noms Descripteurs de fichiers
ouverts
Exemple : 0 (entrée standard)

1 (sortie standard)

2 (sortie d’erreur )

3 (descripteur d’écriture f1)

4=fd[0] (lecture tube)

5=fd[1] ( écriture tube)

L’argument de pipe() est un tableau de deux descripteurs de fichier (un descripteur


de fichier est du type int en C). Lorsque le tuyau a été créé, le premier descripteur,
tuyau[0], représente le côté lecture du tuyau et le second, tuyau[1], représente le
côté écriture.

RQ : L’accès au tube se fait via les descripteurs. Seul le processus créateur du tube
et ses descendants (ses fils) peuvent accéder au tube.

Programmation Système sous UNIX


2 éme ing 87
Les tubes sans noms
Exemple d’utilisation : Ecrire un if(write(tube[1],buffer,256)!=256)
programme en C qui crée un tube {perror(« write ») ; exit(EXIT_FAILURE) ;}
écrit dedans puis lit les donnés .
fprintf(stdout, “Lecture dans tube”)
# include <stdio.h> if(read(tube[0],buffer,256)!=256)
# include <unistd.h> {perror(« read ») ; exit(EXIT_FAILURE) ;}

int main(void) fprintf(stdout, “Vérification”)


{int tube[2]; for(i=0;i<=256;i++)
char buffer[256]; if (buffer[i]!=i)
int i; fprintf(stdout, “Erreur i=%d et buffer=
fprintf(stdout, “Création tube”) %d” , i, buffer[i]);
// affichage à la sortie standard
if(pipe(tube) !=0){perror(« pipe ») ; return EXIT_SUCCESS;
exit(EXIT_FAILURE) ;} }
for(i=0;i<=256;i++)
buffer[i]=i;

fprintf(stdout, “Ecriture dans tube”)


Programmation Système sous UNIX
2 éme ing 88
Les tubes sans noms
Communication entre père/fils :
Les tubes sans nom sont, en général, utilisés pour la communication entre un
processus père et ses processus fils, avec un d’entre eux qui écrit sur le tube, appelé
processus écrivain, et l’autre qui lit à partir du tube, appelé processus lecteur. La
séquence d’événements pour une telle communication est comme suit :

- Le processus père crée un tube de communication sans nom en utilisant l’appel


système pipe()
-Le processus père crée un ou plusieurs fils en utilisant l’appel système fork()
-Le processus écrivain ferme le fichier, non utilisé, de lecture du tube
-De même, le processus lecteur ferme le fichier, non utilisé, d’écriture du tube
-Les processus communiquent en utilisant les appels système write() et read()
-Chaque processus ferme son fichier lorsqu’il veut mettre fin à la communication
via le tube

Programmation Système sous UNIX


2 éme ing 89
Les tubes sans noms
Pére  écrivain ( ferme fd[0] )
fils  lecteur (ferme fd[1])

Programmation Système sous UNIX


2 éme ing 90
Les tubes sans noms
Application : Ecrire un programme en C qui crée un tube de communication entre un
processus et son fils le flux de données passe du fils au père.

#include <sys/types.h> // types Fils  écrivain ( ferme fd[0] )


#include <unistd.h>
Pére  lecteur (ferme fd[1])
#include <stdio.h>
#define R 0
#define W 1
int main()
{
int fd [2];
char message[100];
int nboctets;
char phrase = "message envoyé au père par le fils " ;

pipe(fd ); // création d’un tube sans nom


if ( fork () ==0) // création d’un processus fils
{

Programmation Système sous UNIX


2 éme ing 91
Les tubes sans noms
// Le fils ferme le descripteur non utilisé de lecture
close(fd[R]);
// dépôt dans le tube du message
write(fd[W],phrase, strlen(phrase)+1) ;
// fermeture du descripteur d’ écriture
close ( fd[W]) ;
}

else
{
// Le père ferme le descripteur non utilisé d’ écriture
close(fd[W]) ;
// extraction du message du tube
nboctets = read (fd[R], message,100) ;
printf ( "Lecture %d octets : %s\n", nboctets , message) ;
// fermeture du descripteur de lecture
close ( fd[R ]) ;
}
return 0;
}
Programmation Système sous UNIX
2 éme ing 92
Les tubes sans noms
Redirection de sortie et d’entrée standards
Une technique couramment employée avec les tuyaux est de relier la sortie
standard d’une commande à l’entrée standard d’une autre, comme quand on tape (
who | wc ). Les appels système utilisés sont dup et dup2.

ls | wc

Processus Processus
écrivain lecteur

Il faut relier l’entrée


Il faut relier la sortie
std du processus
std du processus
lecteur à la sortie
écrivain à l’entrée du
du tube
tube

Programmation Système sous UNIX


2 éme ing 93
Les tubes sans noms
Prenons comme exemple la redirection de l’entrée standard vers le côté lecture du
tuyau :
On ferme l’entrée standard (descripteur de fichier numéro 0 ou, de manière plus
lisible, STDIN_FILENO, défini dans <unistd.h>). Le plus petit numéro de descripteur
non utilisé est alors 0.
On appelle dup() avec le numéro de descripteur du côté lecture du tuyau comme
argument. L’entrée standard est alors connectée au côté lecture du tuyau.
On peut alors fermer le descripteur du côté lecture du tuyau qui est maintenant
inutile puisqu’on peut y accéder par l’entrée standard.

Programmation Système sous UNIX


2 éme ing 94
Les tubes sans noms
Application : Ecrire un programme qui réalise l’exécution parallèle
de deux commandes shell. Un tube est créé pour diriger la sortie standard
de la première commande vers l’entrée standard de la deuxième .

#include <unistd.h> //pour fork , close ...


#include <stdio.h>
#define R 0
#define W 1
int main(int argc , char argv [])
{
int fd [2];
pipe(fd ); // création d’un tube sans nom
if ( fork () !=0)
{ // Le père ferme le descripteur non utilisé de lecture
close(fd[R ]) ; // duplication de la sortie standard ( son descripteur est 1)
dup2(fd[W], 1) ; // fermeture du descripteur d’ écriture
close ( fd[W]) ; // exécute le programme écrivain
if (execlp(argv [1], argv [1], NULL) ==1);
perror("execlp" ) ;
Programmation Système sous UNIX
} 2 éme ing 95
Les tubes sans noms

else // processus fils ( lecteur )


{
// fermeture du descripteur non utilisé d’ écriture
close(fd[W]) ;
// duplication de l ’ entrée standard ( son descripteur est 0)
dup2(fd[R],0) ;
close ( fd[R ]) ; // fermeture du descripteur de lecture
// exécute le programme lecteur
execlp(argv [2], argv [2], NULL) ;
perror("connect" ) ;
}
return 0 ;
}

Programmation Système sous UNIX


2 éme ing 96

Vous aimerez peut-être aussi