© D. Mathieu
mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique
Créé le 04/08/2000 -
Dernière mise à jour : 05/09/2001
Variables d'environnementLes fonctions système
Environnement et fonction main()
Variable environ
Environnement et lancement d'un exécutable
Les fonctions système concernant directement les processusGroupes de processus
Autres fonctions système liées à l'existence des processus
Autres fonctions système
Sous Unix, un processus est toujours créé par un autre processus (sauf bien sûr le premier). Le mécanisme est le suivant : tout se passe comme si le processus qui demande la création était totalement dupliqué (virtuellement). Il y a alors deux processus, appelés le père et le fils, pratiquement identiques (à très peu de détails près) qui continuent à se dérouler en faisant exactement la même chose. Le père est le processus qui a gardé le pid initial, le fils quant à lui a reçu un nouveau pid correspondant à un nouveau bloc de contrôle de processus dans la table.
La seconde étape consiste souvent à substituer au code de l'un des processus (en principe le fils) un nouveau code exécutable, afin que les deux processus soient différents. Ce code est chargé à partir de la mémoire secondaire (disque).
Il n'y a aucun lien entre des processus "frères" ou "cousins". En revanche, un processus reste attaché à son père jusqu'à la disparition de l'un des deux. Un processus a donc toujours un père. Si son "vrai" père disparaît avant lui, il est automatiquement rattaché à un père adoptif (le processus de pid 0 ou 1 selon les systèmes Unix). Lorsqu'un processus meurt, son père reçoit, en standard, un signal SIGCHLD. Tout processus est donc averti, s'il le veut, de la disparition de ses processus fils. De même un processus peut se mettre en attente de la fin de l'un, quelconque ou particulier, de ses fils.
Un processus peut avoir, sur les fichiers, les droits (user, group, others) soit de l'utilisateur qui l'a créé, soit du fichier qui contient le code exécutable.
Elles apparaissent sous la forme d'une succession de lignes de la forme nom=valeur, par exemple :
HOSTNAME=duo.iut.univ-aix.fr
LOGNAME=mathieu PATH=/usr/local/bin:/usr/local/jdk1.2.2/bin:/usr/ucb:/bin:/usr/bin:/usr/lib:/etc:/usr/sbin:/usr/bin/X11:. HOME=/users/prof/mathieu SHELL=/bin/csh USER=mathieu |
De nombreux compilateurs C/C++, en particulier sous Unix, proposent une "surcharge" (il n'y a pas de surcharge en C) particulière de la fonction main() :
int main (int argc, char * argv [], char * envp []); |
dans laquelle envp est un tableau de pointeurs de chaînes de caractères C (NTCTS), le dernier pointeur devant être nul.
Bien que non conforme strictement aux normes ISO de C et de C++, cette fonction permet à une application de récupérer l'ensemble des variables d'environnement, comme par exemple :
int main (int argc, char * argv [], char * envp [])
{ for (int i = 0; envp [i]; ++i) cout << envp [i] << endl; // ... } // main() |
Le mécanisme de passage des paramètres de la fonction main() et la localisation de ces informations dans la mémoire virtuelle sont décrits dans le cours consacré à la gestion mémoire sous Linux.
extern char ** environ; |
si la bibliothèque GNU C est utilisée (si la macro __USE_GNU est définie).
Dans le cas contraire, il suffit d'ajouter la ligne ci-dessus au code, la définition de cette variable est de toutes façons incluse au moment de l'édition de liens :
extern char ** environ;
void fct (void)
// ... } // fct() |
De plus, la bibliothèque GNU C et la bibliothèque standard du C pour Linux (niveau 3) proposent la fonction getenv() qui permet de récupérer la "valeur" d'une variable d'environnement. La bibliothèque standard du C pour Linux propose aussi setenv(), unsetenv() et putenv() qui permettent à un processus toutes les autres opérations sur les variables d'environnement (ajout, suppression, modification).
Le tableau ci-dessous résume les caractéristiques des différentes fonctions de lancement d'un processus sous Unix :
Fonction | Recherche dans PATH | Ligne de commande | Tableau d'environnement |
execl() | Non | Liste | Non |
execle() | Non | Liste | Oui |
execlp() | Oui | Liste | Non |
execv() | Non | Tableau | Non |
execve() | Non | Tableau | Oui |
execvp() | Oui | Tableau | Non |
Remarque : le postfixe l signifie liste (d'arguments), le postfixe v signifie vecteur (d'arguments), le postfixe p signifie path, le postfixe e signifie environnement.
Bien que n'étant pas spécifiquement des fonctions de manipulation de processus, certaines fonctions système sont liées à leur existence et peuvent y être rattachées
Les fonctions dup() et dup2() n'ont aucun lien avec l'existence des processus. Cependant leur utilisation est indissociable des fonctions exec...() et pipe().
La plupart des systèmes Unix utilisent la notion de groupes de processus (process group) pour représenter un ensemble de processus collaborant à une même activité. Un processus possède non seulement un numéro de processus (pid : process ident) personnel, mais aussi le numéro du groupe de processus auquel il appartient, et qui lui est attribué par le système.
La notion de groupe de processus est utilisée dans deux cas :
Il est possible de connaître le numéro de groupe de n'importe quel processus grâce à la fonction système getpgid(). De même tout processus peut changer son propre numéro de groupe de processus, ou celui d'un autre processus grâce à la fonction système setpgid().
Lorsqu'un shell lance une commande, il crée un processus fils (fork()) qui hérite de son numéro de groupe, mais ce numéro de groupe est immédiatement remplacé par le pid du fils, qui devient leader d'un nouveau groupe. Ainsi, un signal SIGKILL envoyé au groupe d'un processus ne peut pas être propagé au shell qui l'a lancé.
Lorsqu'un shell lance simultanément plusieurs commandes faisant partie d'une même activité (par exemple commandes enchaînées par un pipe (|), elles font toutes partie du même groupe.
© D. Mathieu
mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique