chapitre 3: Gestion des processus
jnouedoni@[Link]
February 22, 2022
à la fin de ce chapitre, je dois être capable de :
1. Utiliser les primitives C pour créer un processus
2. Exécuter un programme à partir d’un processus
3. Obtenir des informations sur un processus
4. écrire des programmes C manipulant des processus
1 Introduction
Le troisième chapitre de ce cours s’est interessé à la manipulation des proces-
sus à travers les utilitaires ou les commandes du Système d’exploitation Unix.
Le langage C1 permet aux programmeurs de créer, exécuter, faire commu-
niquer ou transmettre des signaux à des processus en utilisant directement
les primitives ou instructions C. Ce chapitre s’interesse aux constructions of-
fertes pour la manipulation des processus. Il passe tour en tour en révue: le
mécanisme de création de processus, l’exécution de commandes système ou 2
par les processus, la terminaison des processus et initie à la communication
inter-processus.
2 la création des processus en C
Deux techniques peuvent être utilisées pour créer des processus en C. La
première qui consiste à employer la primitive system() est relativement
simple à utiliser mais se revèle inéfficace et comporte de nombreux risques
sécuritaires. La seconde qui concerne l’usage de la fonction fork() semble
complexe mais offre plus de fiabilité, flexibilité, rapidité et sécurité.
1
Langage à partir duquel le système Unix a été crée
2
autres programmes
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
2.1 La primitive system 2
2.1 La primitive system
La fonction system() fournit un procédé simple d’exécution d’une commande
du shell à partir d’un programme C de la même façon que si la commande
était entrée à partir d’un shell de commandes. Dans la réalité, la fonction
system crée un sous shell ou sous processus exécutant la commande transmise
en argument.
2.1.1 Syntaxe et valeur de retour de la fonction system
La fonction system considère comme argument d’entrée une chaı̂ne de car-
actères indiquant la commande à exécuter. Sa syntaxe est indiquée comme
suit: system(char*) Elle retourne une valeur entière dont la signification
est :
127, lorsque le shell ne peut être exécuté
-1 en cas d’erreur
Puisque la fonction system invoque un nouveau shell, elle est sujette aux
limitations et failles sécuritaires du shell système. Le comportement de
cette fonction varie d’un environnement unix à un autre. la fonction sys-
tem nécessite l’inclusion de la librairie 3 : stdlib.h
2.1.2 Exemple d’utilisation de cette fonction
#include ¡stdlib.h
int main()
{
int valeur retour ;
valeur retour=system(“ ls -all /”);
return valeur retour ;
}
Ce programme crée un sous-processus du shell qui exécute la commande “ls
-all”.
2.2 La primitive fork()
la primitive fork() permet de créer deux processus:
le processus père
3
biliothèque ou fichier d’en-tête
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
2.2 La primitive fork() 3
le processus fils
la fonction fork() exige l’inclusion des librairies4 C suivant :
1. stdlib.h
2. unistd.h
3. sys/types.h
Lorsqu’un programme en cours d’exécution comporte l’instruction fork(),
celle-ci5 crée deux processus exécutant le même programme dans deux con-
textes différents. Ces deux processus étant distincts, ils possèdent forcément
des PID différents.
2.2.1 valeur de retour et syntaxe de la fonction fork()
La fonction fork() n’admet aucun argument d’entrée mais retourne deux
valeurs de retour. Ces valeurs de retour sont du type :pid t6 .
La valeur de retour de la fonction fork() est nulle chez le processus fils et
non nulle chez le processus père. La valeur non nulle retournée chez le pro-
cessus père correspond au PID du processus fils. nomvariable=fork()
2.2.2 Exemples d’utilisation de la fonction fork()
L’exemple de code suivant crée 2 processus affichant les messages “je suis le
père pour l’un “ et “je suis le fils “ pour l’autre. # include stdlib.h
# include unistd.h
# include sys/types.h
pid t numprocessus;
int main()
{
numprocessus=fork();
if (numprocessus 0)
printf(”je suis le processus père”);
else
printf(”je suis le processus fils”);
return 0;
}
4
fichiers d’en-tête
5
l’instruction
6
valeur entière définie dans la bibliothèque sys/types.h
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
2.3 getpid() et getppid() 4
Il est possible d’utiliser la fonction getpid() pour déterminer la valeur ex-
acte du numéros de chaque processus. Cette fonction permet donc à un
programme en cours d’exécution de fixer son identifiant. L’extrait de code
suivant permet de créer deux processus père et fils affichant chacun son pid.
#include stdlib.h
#include unistd.h
#include sys/types.h
pid t numprocessus;
int main()
{
numprocessus=fork();
if (numprocessus)
{
printf(”je suis le processus père”);
printf(” mon pid a pour valeur :%d”, getpid());
}
else
{
printf(”je suis le processus fils”);
printf(” mon pid a pour valeur :%d”, getpid());
} return 0;
}
2.3 getpid() et getppid()
La primitive getppid() retourne le numéros du processus grand père d’un
processus alors que la primitive getpid() retourne le numéros du processus
parent d’un [Link], déjà décrit dans le chapitre sur la gestion des
processus, chaque processus possède un père. On obtient ainsi un arbre de
processus dont l’ancêtre est init. #include stdlib.h
#include unistd.h
#include sys/types.h
pid t numprocessus;
int main()
{
numprocessus=fork();
if (numprocessus)
{
printf(”je suis le processus père”);
printf(” mon pid a pour valeur :%d”, getpid());
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
3 Exécution de programmes par les processus 5
}
else
{
printf(”je suis le processus fils”);
printf(” mon pid a pour valeur :%d”, getpid());
printf(” le pid de mon grand-père a pour valeur :%d”, getppid());
} return 0;
}
3 Exécution de programmes par les proces-
sus
Lorsqu’un processus est crée, il hérite du même code que le programme qui
le crée. Pour établir une séparation entre le processus père et le processus fils
du point de vue code exécuté, il est posssible de faire usage des primitives
exec pour amener le fils à exécuter un autre programme que le processus
père. La famille de fonction exec regroupe diverses catégories repertoriées à
travers leur orthographe:
1. les fonctions exec dont l’orthographe contient la lettre p tel que :
execvp, execlp. Ces fonctions acceptent un nom de programme en
paramètre et recherchent ce programme dans les repertoires indiqués
par la variable système PATH. Les argument du programme sont four-
nis dans un tableau dont chaque indice correspond à une chaı̂ne de
caractères. Le dernier indice du tableau devant avoir la valeur NULL7 .
2. les fonctions exec dont l’orthographe contient la lettre e: execve, execle.
Ces fonctions acceptent une liste d’arguments dont la fin est indiquée
par la chaı̂ne NULL et une table de variables d’environnement comme
second argument. Chaque chaı̂ne de la liste des arguments est de la
forme variable=valeur.
3. les fonctions exec dont l’orthographe contient la lettre l: execl, execlp.
Ces fonctions admettent la fourniture des arguments sous forme d’une
liste. Chaque argument de la liste étant une chaı̂ne de caractères ou
encore pointeur sur un caractère. Le dernier élément de la liste des
arguments est l’argument null dont la valeur correspond à NULL pour
désigner une chaı̂ne vide 8
7
pointeur vide
8
En C,pour un pointeur sur une chaı̂ne de caractères, NULL désigne une chaı̂ne vide
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
3.1 primitive execvp 6
4. les fonctions exec ayant dans leur orthographe les lettres l,e et p ont
une signification combinant les explications ci-dessus
Le tableau suivant mentionne toutes les fonctions exec offertes par le langae
C
primitives format d’argument passage d’environnement recherche avec PATH
execl liste automatique non
execv tableau automatique non
execle liste manuel non
execve tableau manuel non
execlp liste automatique oui
execvp tableau automatique oui
Table 1: liste des fonctions exec
3.1 primitive execvp
La fonction execvp, exécute un programme passé en paramètre. La liste des
arguments de ladite fonction est fournie dans un tableau de pointeur sur
des chaı̂nes de caractères. la syntaxe de cette fonction est : execvp(char*
program, char* arglist) l’argument program est une chaı̂ne de caractères qui
fournit le nom du programme à exécuter. cette fonction retourne une valeur
en cas d’erreur d’exécution. #include stdlib.h
#include unistd.h
#include sys/types.h
pid t numprocessus;
int main()
{
char** tab ;
char** param;
char* prog, prog2;
tab=(char**)malloc(sizeof(char)*10);
tab=”ps”, ”-ef”;
param=(char**)malloc(sizeof(char)*10);
param=”ls”, ”-all”, ”/”, NULL ;
numprocessus=fork();
if (numprocessus)
{ printf(”je suis le processus père”);
printf(”mon pid a pour valeur :%d”, getpid());
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
3.2 primitive wait 7
printf(”voici la liste des processus”);
prog=(char*)malloc(sizeof(char)*100);
prog=”ps”;
execvp(”ps”, tab);
} else
{
printf(”je suis le processus fils”);
printf(”mon pid a pour valeur :%d”, getpid());
// printf(”le pid de mon grand-père a pour valeur :%d”, getppid());
prog2=(char*)malloc(sizeof(char)*100);
prog2=”ls”;
execvp(”ls”, param);
}
return 0;
}
L’extrait de programme ci-dessus crée deux processus. Le processus père
liste les processus en cours d’exécution alors que le processus fils fournit la
liste des fichiers du repertoire racine. Dans ce programme, la fonction malloc
est utilisée pour reserver en mémoire centrale un espace pour conserver les
données d’une chaı̂ne de caractères. La fonction execvp permet d’exécuter
une commande à prtir du shell unix.
3.2 primitive wait
La fonction wait provoque la suspension du processus appelant cette fonction.
Ainsi, si un processus père invoque cette fonction, l’exécution de ce dernier
est suspendu jusqu’à ce que l’un de ses processus fils se termine. Il n’est pas
possible de choisr le processus fils dont le père doit attendre la terminaison.
3.2.1 syntaxe de la fonction wait
int wait(int* statusp) la fonction wait considère en entrée un pointeur sur
un entier et retourne une valeur entière. La valeur retournée peut être -1, en
cas d’erreur ou alors l’identifiant d’un processus. Pour examiner le mode de
sortie d’un processus exécuté, il est indispensable de consulter la valeur de
statusp en utilisant pour cela une des macros ou fonctions suivantes :
1. WEXITSTATUS pour extraire la valeur de retour du processus fils
2. WIFEXITED pour savoir si le processus fils s’est achevé normalement
3. WTERMSIG pour obtenir le code du signal ayant provoqué la termi-
naison du processus fils
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
3.2 primitive wait 8
#include stdlib.h
#include unistd.h
#include sys/types.h
pid t numprocessus;
int main()
{
char** tab ;
char** param;
char* prog, prog2;
tab=(char**)malloc(sizeof(char)*10);
tab=”ps”, ”-ef”;
param=(char**)malloc(sizeof(char)*10);
param=”ls”, ”-all”, ”/”, NULL ;
numprocessus=fork();
if (numprocessus)
{ printf(”je suis le processus père”);
wait(&numprocessus) if (WIFEXITED(numprocessus) { printf(”le processus
fils s’ est normalement achevé, avec comme code de retour:%d”, WEXIT-
STATUS(numprocessus)); } else printf(”voici la liste des processus”);
prog=(char*)malloc(sizeof(char)*100);
prog=”ps”;
execvp(”ps”, tab);
} else
{
printf(”je suis le processus fils”);
printf(”mon pid a pour valeur :%d”, getpid());
prog2=(char*)malloc(sizeof(char)*100);
prog2=”ls”;
execvp(”ls”, param);
}
return 0;
}
le langage C propose des variantes plus performantes de la fonction wait
telles que : wait3 et wait4. Ces fonctions permettente de nettoyer de manière
asynchrone le contexte d’exécution des processsus zombies.
3.2.2 Processus zombie
Normalement, un processus père attend la fin de l’exécution de ses processus
fils. L’appel de la fonction wait par un processus père ne lui permet pas
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
3.3 transmission des signaux aux processus 9
seulement d’attendre la fin de l’exécution de ses fils mais est aussi utile pour
nettoyer l’environnement d’exécution du processus fils. Lorsqu’un processus
fils s’achève alors que son père n’attend pas sa fin d’exécution, ledit processus
fils devient un processus zombie. Un processus zombie est donc un processus
qui s’est terminé sans que son contexte d’exécution n’ ait été nettoyé par
son processus père. l’extrait de code suivant produit un processus fils zombie
#include stdlib.h
#include unistd.h
#include sys/types.h
pid t numprocessus;
int main()
{
numprocessus=fork();
if (numprocessus)
{
printf(”je suis le processus père”);
sleep(10000);
}
else
{
exit(0); } return 0;
}
la primitive sleep invite le père à attendre pendant 10000 ms avant de pour-
suivre son exécution. Elle ne permet pas au processus père d’attendre la
terminaison de son fils.
3.3 transmission des signaux aux processus
A partir d’un programme C, il est possible de transmettre un signal à un
processus. Pour cela, il suffit d’utiliser la primitive kill de la manière suiv-
ante:
kill(pid t child pid,int signal)
child pid désigne l’identifiant d’un processus; signal indique le numéro du
signal devant être transmis au processus dont l’identifiant est child pid. En
particulier, pour provoquer la terminaison d’un processus, il suffit donc de
transmettre le signal SIGTERM au processus dont on souhaite l’achèvement.
Il est important de signaler qu’avant toute utilisation de la fonction kill, il
faut inclure les bibliothèques: signal.h et sys/types.h
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
4 initiation aux techniques de communication inter-processus 10
4 initiation aux techniques de communica-
tion inter-processus
4.1 Définition
la communication inter processus ou IPC inter process communication désigne
un ensemble de techniques permettant aux processus de s’échanger des in-
formations. C’est aussi le transfert des données entre divers processus.
4.2 Les mécanismes de communication inter-processus
Les techniques suivantes peuvent être utilisées pour favoriser les communi-
cations inter-processus:
1. les mémoires partagées
2. les tubes ou pipes
3. les FIFO
4. les sockets
5. la technique dite Mapped Memory
4.3 les mémoires partagées
Les mémoires partagées représentent le procédé le plus simple de communica-
tion inter-processus. Ici, les processus s’échangent des données en accédant à
la même zone mémoire, pour y lire ou écrire des données. Ce mécanisme IPC
est le plus rapide des techniques de communication interprocessus. Cepen-
dant, les mémoires partagées nécessitent l’utilisation des sémaphores comme
mécanisme de synchronisation.
4.4 Mapped Memory
Le mécanisme Mapped Memory est une technique de communication inter-
processus permettant à plusieurs processus de s’échanger des données par
l’intermédiaire d’un fichier partagé.
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]
4.5 Les tubes 11
4.5 Les tubes
Encore appelé pipe ou conduit, un tube est un mode de communication inter-
processus unidirectionnel. La communication est unidirectionnelle en ce sens
que certains processus peuvent écrire des données dans le tube pendant que
d’autres ne pourront que lire les données. Les processus rédacteurs écrivent
à un bout du tube et d’autres processus lisent à l’autre bout du tube
4.6 les FIFO
Les FIFO9 ou file de message sont une variante de tubes. Les fifo sont des
tubes possédant des noms dans le système de fichiers.
4.7 les sockets
les sockets sont le mécanisme de communication inter processus le plus évolué.
Ils permettent à des processus présents sur la même machine ou des ma-
chines distinctes de communiquer ou s’échanger des données. Les applica-
tions réseau tels que telnet, ftp, rlogin, talk ou le www exploitent le principe
de communication par socket. Un Socket est en réalité la combinaison adresse
ip et numéro de port.
Le chapitre suivant déatillera ces techniques de communication interpro-
cesssus.
9
First in First out
Complexe Universitaire Siantou
Cycle Licence profressionnelle
Gestion des ProcessusProgrammation des processus jnouedoni@[Link]