Communication Entre Processus
Communication Entre Processus
Communication Entre Processus
2
Introduction
• Un processus est l'abstraction d'un programme exécute en mémoire.
• Les processus sont des entités a priori indépendantes.
• Chaque processus dispose de ses données et de sa pile d’exécution est exécute un code
non modifiable qui peut être partagé.
3
Les informations attachees a un processus
L'OS dispose de renseignement concernant un processus :
• le pid i.e. numéro identificateur du processus ;
• le ppid i.e. numéro identificateur du processus père ;
• l'uid i.e. numéro identificateur du propriétaire du processus ;
• le numéro du groupe auquel appartenait le propriétaire du processus (il
peut appartenir a plusieurs groupe) ;
• l'heure et la date de création du processus ;
• des statistiques sur les ressources (processeur, etc.) utilisées ;
• la taille mémoire actuellement utilisée par le processus (en distinguant
chaque composante : swap, tas, code, données, etc).
Mais aussi,
• un masque indiquant la sensibilité aux signaux ;
• son état (en cours d‘exécution, zombie, arrête, suspendu, etc.) ;
• la priorité d'exécution ;
4
Les informations attachees a un processus
• Chaque processus est représente dans l'OS par un bloc de contrôle de processus
contenant les informations suivantes :
• l‘état du processus (nouveau, prêt, en cours d'exécution, en attente, arrête,
etc.) ;
• les numéros associes au processus ;
• l‘état des registres du microprocesseur associes au processus et notamment :
– les différents numéros de segments (mémoire, code, pile, etc.) ;
– un pointeur sur la prochaine instruction a exécuter ;
– les registres a usage généraliste.
– la liste des fichiers ouvert et l'ensemble des informations associées aux
entrées-sorties ;
– des statistiques sur l'utilisation des ressources de la machine (temps
d'occupation du processeur, etc.) ;
– les limites maximales de la mémoire (début et fin des ces espaces).
5
Une vision abstraite d'un processus
• Son graphe de transitions d‘état
7
Clonage d'un processus : l'appel systeme fork
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h> /* La structure de ce code est typique du */
#include <unistd.h> /* clonage d'un processus. */
#include <stdlib.h>
int main(void){
int status,pid = 0 ;
pid = fork() ; /* L'appel système permettant le clonage */
if (pid == 0){
printf("fils :%d\n",getpid()) ; /* le code du processus fils */
exit(1) ; /* un appel permettant la terminaison de ce processus */
}
else { /* le code du processus père qui utilise */
printf("pere :%d\n",getpid()) ; /* un appel pour connaitre son pid */
printf("mon fils :%d\n",pid) ;
wait(&status) ; /* Un appel permettant au père attend la mort de son fils avant de terminer. */
exit(++status);
}
return 0 ; /* cette instruction n'est jamais exécutée */
}
8
Clonage d'un processus : l'appel systeme fork
L'appel pid_t fork(void); provoque le clonage du pere en fils :
les segments de mémoire sont dupliques (code, donnée, etc) ;
cela implique que père et fils partagent les données définies avant le
clonage (variables mais aussi flux ouvert, etc.) ;
l'exécution des processus père et fils poursuivent leurs exécutions
juste après le clonage.
L'appel pid_t getpid(void); (resp. pid_t getppid(void);) retourne
l'identificateur (resp. du père) du processus courant.
L'appel void exit(int status); provoque la terminaison normale du
processus et retourne l'entier status au père. Dans l'exemple
précédant le fils envoit 1 au père qui retourne 2 au shell.
L'appel pid_t wait(int *status); force le père a attendre la
terminaison d'un processus de sa parente (qui lui envoi un signal
stocke dans l'espace pointe par status) dont le pid est retourne par
l'appel.
9
Exemples 1
main () Le processus père exécutera le bloc 1. Puis il
{ créera un fils identique par fork et exécutera le
bloc 3 puisque fork lui retournera une valeur
int pid_fils; non nulle.
bloc1
if ((pid_fils = fork()) == 0) Le processus fils n'exécutera pas le bloc 1 car à
sa création, son compteur ordinal pointera sur
bloc2
la ligne contenant fork. Comme fork lui
else retourne 0, il exécutera le seul bloc2.
bloc3
}
L'affichage des résultats des blocs 2 et 3 peut être entrelacé, et pas nécessairement
de façon identique d'une exécution à une autre.
10
Exemples 2
main () Le processus père exécutera le bloc 1. Puis il
{ créera un fils identique par fork et exécutera le
bloc 2 puisque fork lui retournera une valeur
int pid_fils; non nulle.
bloc1
if (fork()) Le processus fils n'exécutera pas le bloc 1 car à
sa création, son compteur ordinal pointera sur
bloc2
la ligne contenant fork. Comme fork lui une
else valeur non nulle, il exécutera le seul bloc3.
bloc3
}
L'affichage des résultats des blocs 2 et 3 peut être entrelacé, et pas nécessairement
de façon identique d'une exécution à une autre.
11
Exemples 3
main ()
{
int m,n;
printf ("processus père. Fils non encore créé\n");
if (fork () == 0)
{
printf ("pid du fils %d\n", getpid());
exit (1);
}
else {
printf ("pid du père %d\n", getpid());
m = wait (&n);
printf ("fin du processus de pid %d avec valeur de retour de wait %d\n",m,n);
}
}
12
Mutation d'un processus : la famille d'appels
systeme exec
• Un processus existant peut subir une mutation par un appel
système en un processus construit a partir d'un exécutable
existant.
#include <unistd.h>
int main(void) {
execl("/bin/ls","ls",NULL) ;
return 1 ; /* Cette commande n'existe plus du fait de la mutation */
}
13
Mutation d'un processus : la famille d'appels
systeme exec
La famille des fonctions de recouvrement (exec)
• Il s'agit d'une famille de 6 fonctions permettant le lancement de
l'exécution d'un nouveau programme par un processus. Le segment de
texte est remplacé par celui du nouveau programme. Il y a recouvrement
en mémoire, mais pas de création d'un nouveau processus.
• Le retour est -1 en cas d'erreur.
• Les 6 fonctions sont execl, execv, execle, execve, execlp, execvp.
14
Mutation d'un processus : la famille d'appels
systeme exec
On peut les répartir en deux groupes :
• les primitives execl pour lesquels le nombre d'arguments du
programme lance est connu. Les arguments sont passes sous forme
de liste ;
– int execlp(const char *file, const char *arg, ...);
– int execle(const char *path, const char *arg , ..., char * const envp[]);
• les primitives execv pour lesquels le nombre d'arguments ne l'est
pas. Les arguments sont passes sous formes de tableau.
– int execv(const char *path, char *const argv[]);
– int execvp(const char *file, char *const argv[]);
15
Quelques règles régissant la communauté des
processus
16
Quelques règles régissant la communauté des
processus
• L'appel system uid_t getuid(void) (resp. int setgid(gid_t gid);)
permet de déterminer le propriétaire (resp. le groupe) du
processus.
• L'appel système int setuid(uid_t uid) (resp. int setgid(gid_t
gid);) permet de modifier le propriétaire (resp. le groupe) d'un
processus.
• Le système d'exploitation lance un grand nombre de processus
dont la fonction est d'assurer les tâches de gestions, par
exemple :
– cups est un gestionnaire d'impression ;
– xscreensaver un gestionnaire pour économiser des
ressources ;
– gpm un gestionnaire de la sourie.
17
Les étapes de la mort d'un processus
18
Les étapes de la mort d'un processus
• Considérons le code
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void){
int res = 0, status = 0 ;
: res = fork() ; /* clonage */
if(!res) exit(status) ; /* le fils termine */
else wait(&status) ; /* le père attend la fin du fils */
return 0 ;
}
19
Les étapes de la mort d'un processus
• A la terminaison d'un processus fils, un lien avec le père demeure jusqu'a
ce que ce dernier se termine a son tour ou appelle wait.
• L'entrée du processus fils dans la table des processus ne se libère pas
immédiatement a sa terminaison. Bien qu'inactif, le processus fils demeure
dans le système en vue d'un éventuel appel wait. C'est un processus
zombie.
20
Notion de signal
• Un signal est émis par un processus vers un autre (ou un
groupe d’autres) processus de même propriétaire (sauf root).
• Le signal peut être rattrapé par le processus destinataire, ce
qui provoque (en général) un déroutement et le lancement
d’une routine spécifique de traitement.
• Après le traitement, le processus reprend où il a été
interrompu.
• En UNIX : la commande kill permet d’envoyer des signaux.
21
Exercice
• Ecrire un programme qui réalise une chaîne
de n processus, Faire imprimer le numéro de
chaque processus et celui de son père.
22
Communication entre processus
23
Communication entre processus
(Unix)
• La communication entre processus (Inter-Process
Communication, ou IPC) est l’un des aspects les plus
importants (et aussi les plus délicats) de la
programmation de systèmes.
24
Communication entre processus
(Unix)
• Dans Unix, la communication entre processus peut se faire
de plusieurs manières différentes :
• Communication asynchrone au moyen de signaux
• Communication par fichiers ou par tubes (pipes, FIFOs)
• Communication par files de messages
• Communication par mémoire partagée et par sémaphores
• Communication par sockets, utilisés dans les réseaux, mais
aussi en local
25
Signaux
• Un signal est "un message très court" qu’un
processus peut envoyer à un autre processus,
pour lui dire qu’un événement particulier est
arrivé.
• Un signal peut être émis par un processus ou
par le système d’exploitation.
• Le processus pourra mettre en oeuvre une
réponse décidée et pré-définie à l’avance
(handler).
26
Signaux vs interruption
27
Signaux!
• Les signaux sont un mécanisme de bas niveau.
Ils doivent être manipulés avec précaution car
leur usage recèle des pièges (en particulier le
risque de perte de signaux).
• Ils sont néanmoins utiles lorsqu’on doit
contrôler l’exécution d’un ensemble de
processus (exemple : le shell) ou que l’on
traite des événements liés au temps.
28
Fonctionnement des signaux
processus p
retour au point où le processus a
été interrompu (sauf si le traitant
a pour effet de tuer le processus)
29
Fonctionnement des signaux
• Il existe différents signaux, chacun étant identifié par
un nom symbolique (ce nom représente un entier)
• Chaque signal est associé à un traitant par défaut
• Un signal peut être ignoré (le traitant est vide)
• Le traitant d’un signal peut être changé (sauf pour 2
signaux particuliers)
• Un signal peut être bloqué (il n’aura d’effet que
lorsqu’il sera débloqué)
• Les signaux ne sont pas mémorisés
30
Quelques exemples de signaux
31
Les effets de la réception
de ces signaux sur un
processus sont :
Term : le processus se
termine ;
Core : Term + copie de la
mémoire dans un fichier
core ;
Stop : suspend
l'exécution du processus.
32
États d’un signal
Qu’est-ce qui empêche que le signal soit
immédiatement traité dès qu’il est reçu ?
• Le signal peut être bloqué, ou masqué (c’est à
dire retardé) par le destinataire. Il est délivré
dès qu’il est débloqué
• En particulier, un signal est bloqué pendant
l’exécution du traitant d’un signal du même
type ; il reste bloqué tant que ce traitant n’est
pas terminé
33
Les primitives de gestion des signaux
• L'appel système :
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
34
Les primitives de gestion des signaux
35
Exemple 1 : traitement d’une interruption
du clavier
• Il suffit de redéfinir le traitant de SIGINT (qui par défaut tue le
processus interrompu)
37
La communication par tubes
• Un tube est matérialisé par deux entrées de la table
des ouvertures de fichiers, une de ces entrées est
ouverte en écriture (l'entrée du tube), l'autre en
lecture (la sortie du tube).
38
popen() et l’exécution de programmes
distants
• Exemple de commande Unix :
rsh machine com params
– lance sur la machine distante la commande com et
l'on veut récupérer le résultat (sortie standard).
retour = fread(buf,1,nbre_octets,fp);
39
La communication par tubes(c)
• Création de tubes ordinaires (pipes)
Un processus ne peut utiliser que les tubes qu'il a créés
lui-même par la primitive pipe ou qu'il a hérités de
son père grâce à l'héritage des descripteurs à travers
fork() et exec().
# include <unistd.h>
int pipe (int p[2]);
p[0] correspond au descripteur en mode lecture
p[1] correspond au descripteur en mode écriture
40
La communication par tubes
Lecture dans un tube
On utilise l'appel système read.
int nb_lu; /* nb de caractères lus */
nb_lu = read(p[0], buffer, TAILLE_READ);
41
Java et les tubes : création
42
La communication par sockets
• Un Socket est un point de communication bidirectionnelle entre
applications
• Introduit dans Berkeley Unix 4.2 (BSD) en 1981
• Représentation point à point d’un flux de données Un programme peut
– Écrire des données
– Lire des données
43
Schéma de communication des sockets
Un socket est
associé à un port de
communication pour
différencier les
applications réseau
sur une même
machine
44
Fonctions d’un sockets
• 4 fonctions principales:
• Se connecter à une machine distante
• Envoyer des données
• Recevoir des données
• Fermer la connexion
• Un socket ne peut se connecter qu’à une seule
machine
• Un socket ne peut pas être se reconnecter après la
fermeture de connexion
45
Java pour Socket
L’API java fourni un package java.net pour
l’utilisation des packages
• java.net.Socket pour l’implémentation coté
client
• java.net.ServerSocket pour l’implémentation
coté serveur
46
Instanciation d’un socket
• La création d’un socket se fait à l’aide de l’un de ces
constructeurs
• public Socket(String host, int port) throws
UnknownHostException, IOException
• public Socket(InetAddress address, int port) throws
IOException
• public Socket(String host, int port, InetAddress localAddr,int
localPort) throws IOException
• public Socket(InetAddress address, int port,
InetAddresslocalAddr, int localPort) throws IOException
• Ces constructeurs créent un objet Socket et ouvre
uneconnexion réseau avec la machine distante ‘host’
• Tous ces constructeurs lèvent une exception en cas
d’impossibilité de connexion
47
Connexion d’un socket
• Pour qu’un socket puisse se connecter à une
machine distante, cette dernière doit écouter les
requêtes des clients sur le port spécifié
• les ports TCP d’une machine peuvent aller de 0 à
65535
• Il faut définir au minimum l’adresse de la machine
distante et son port d’écoute pour pouvoir se
connecter
• On peut utiliser les constructeurs pour déterminer
les ports d’écoute d’une machine
48
Quelques services standards
49