Vous êtes sur la page 1sur 43

UNIVERSITE HASSAN 1ER

ECOLE NATIONALE DES SCIENCES APPLIQUÉES


KHOURIBGA

Notion de processus
Objectifs de séance
 Introduire la notion de processus,
 Introduire les différents identifiants qui y sont
associés, leurs significations et leurs utilisations
dans le système
1. Concept de processus

 Un OS exécute une variété de programmes:


• Système Batch – tâches
• Systèmes à temps partagé – Programmes utilisateurs
ou tâches
 Processus – un programme en exécution
 Un processus inclut:
• Compteur de programme (PC)
• Pile (stack)
• Section données
2. Espace de travail

 Les processus sont


Pile d'exécution
composés d’un espace de
travail en mémoire formé de
3 segments :

Données

Code
3. Hiérarchie

Les processus peuvent créer d’autres


processus, formant une hiérarchie
(instruction fork ou semblables)

Arbre de
processus en
UNIX
4. Terminaison de processus

 Un processus qui exécute sa dernière instruction


• pourrait passer des données à son parent
• ses ressources lui sont enlevées
 Le parent termine l’exécution d’un fils
(avortement) pour raisons différentes
• le fils a excédé ses ressources
• le fils n`est plus requis
 etc.
5. États de processus

 Au fur et a mesure qu’un processus s’exécute, il


change d’état
• nouveau: le processus vient d’être créé
• exécutant-running: le processus est en train d’être
exécuté par l ’UCT
• attente-waiting: le processus est en train d’attendre un
événement (p.ex. la fin d ’une opération d’E/S)
• prêt-ready: le processus est en attente d’être exécuté
par l ’UCT
• terminated: fin d’exécution
5. États de processus
6. Sauvegarde d’informations

 En multiprogrammation, un processus exécute sur l’UCT


de façon ….
 Chaque fois qu’un processus reprend l’UCT (transition prêt
 exécution) il doit la reprendre dans la même situation où
il l’a laissée (même contenu de registres UCT, etc.)
 Donc au moment où un processus sort de l’état exécution
il est nécessaire de sauvegarder ses informations
essentielles, qu’il faudra récupérer quand il retourne à cet
état

9
6. Sauvegarde d’informations

PCB = Process Control Block

Représente la
situation
actuelle d’un
processus,
pour le Registres UCT
reprendre
plus tard
7. Lister les processus

 Examiner la liste des


processus présents sur
le système:
 ps ax
 ax permet de voir les
processus endormis, et
ceux qui appartiennent
aux autres utilisateurs
8. Identification par le PID

 Le premier processus du système, init, ainsi que


quelques autres sont créés directement par le noyau au
démarrage
 seule manière de créer un nouveau processus :
• appel-système fork() : dupliquer le processus appelant
(père et fils)
o La différence essentielle : numéro d’identification
PID (Process IDentifier)
• fork() est déclaré dans <unistd.h>: pid_t fork(void);
 Pour connaître son propre PID : appel-système getpid()
• déclaré dans <unistd.h> : pid_t getpid(void);
8. Identification par le PID
 Sous Linux, pid_t est un entier sur 64 bits, mais ce n’est pas le
cas pour tous les Unix.
 Pour assurer une bonne portabilité lors de l’affichage d’un PID,
• Utiliser la conversion %ld de printf()
o fprintf(stdout, "Mon PID est : %ld\n", (long)
getpid());
 La distinction entre processus père et fils peut se faire
directement au retour de l’appel fork()
• zéro si on se trouve dans le processus fils,
• négative en cas d’erreur,
• PID du fils si on se trouve dans le processus père
 Le processus fils peut aisément accéder au PID de son père
(PPID pour Parent PID), getppid(), déclaré dans <unistd.h> :
 pid_t getppid(void);
 le processus père ne peut connaître le numéro du nouveau
processus créé qu’au moment du retour du fork().
8. Identification par le PID

 examiner la hiérarchie des processus en cours sur le


système avec le champ PPID de la commande ps axj :
9. Création de processus

 Le processus fils hérite de son père


• copie des données de son père
• l’environnement de celui-ci
• autres éléments (table des descripteurs de fichiers, etc.)
 fork() est très économe car il utilise une méthode de «
copie sur écriture »
• Ne créer de copies que si un des deux processus a modifié
des informations
• coût très faible en termes de ressources système

9. Création de processus

 En cas d’erreur, fork() renvoie la valeur –1, et la variable


globale errno contient le code d’erreur, défini dans
<errno.h>

ENOMEM Le noyau n’a plus assez de mémoire disponible pour créer un


nouveau processus
EAGAIN Le système n’a plus de place libre dans sa table des
processus
9. Création de processus
Exemple
1. Afficher la valeur de la variable
spéciale $$ du shell
2. Compiler et exécuter « exemple_fork»
3. Que remarquez vous?
4. Mettre le « wait(NULL) en
commentaire, Compiler et exécuter
5. Que remarquez vous?
10. Identification du user correspondant

 chaque processus s’exécute sous une identité précise


• l’UID (User Identifier)

o L’UID réel : celui de l’utilisateur ayant lancé le


programme
o L’UID effectif est celui qui correspond aux
privilèges accordés au processus
o L’UID sauvé est une copie de l’ancien UID effectif
lorsque celui-ci est modifié par le processus
• Généralement, UID effectif = l’UID réel
o applications classiques ne nécessitant pas de
privilège particulier
– Ex : les commandes Unix classiques (ls, cp,
mv…)
10. Identification du user correspondant

 Les appels-système getuid() et geteuid() permettent


respectivement d’obtenir l’UID réel et l’UID effectif du
processus appelant.
• Déclaration dans <unistd.h>
o uid_t getuid (void);

o uid_t geteuid (void);


 uid_t est défini dans <sys/types.h>.
• Entier non signé sur 32 bits
• utiliser la conversion %u pour printf() pour garantir une
bonne portabilité
10. Identification du user correspondant

 UID effectif != UID réel lorsque le fichier exécutable


dispose d’un attribut particulier permettant au processus
de changer d’identité au démarrage du programme
 Soit l’exemple

1. Compiler « exemple_getuid.c »
2. lister les droits d’accès, les UID et GID
3. exécuter
10. Identification du user correspondant

 Imaginons maintenant que root s’attribue le fichier


exécutable et lui ajoute le bit « Set-UID » via la
commande chmod
• $ su
• Password:
• # chown root.root exemple_getuid
• # chmod u+s exemple_getuid
• lister les droits d’accès, les Uid et GID
• Exécuter
• Que remarquez vous?
• Fermer la connection root et réexécuter le programme
exemple_getuid.c, Que remarquez vous?
10. Identification du user correspondant

 UID sauvé
• Copie, effectuée automatiquement par le noyau, de
l’ancien UID effectif lorsque celui-ci est modifié
 Un processus peut toujours demander à changer son UID
effectif ou son UID réel pour prendre la valeur de l’UID
sauvé
 Il est également possible de prendre en UID effectif la
valeur de l’UID réel, et inversement
 Un processus avec le bit Set-UID positionné démarre
avec un UID effectif différent de celui du user qui l’a
invoqué
• Pour effectuer une opération non privilégiée, il peut
demander à remplacer son UID effectif par l’UID réel
10. Identification du user correspondant

 il existe plusieurs appels-système permettant sous Linux


de modifier son UID, et sont déclarés dans <unistd.h>:
• int setuid (uid_t uid_effectif);
• int seteuid (uid_t uid_effectif);
• int setreuid (uid_t uid_reel, uid_t uid_effectif);
o Ils permettent de modifier un ou plusieurs UID du processus
appelant, renvoyant
– 0 s’ils réussissent, ou –1 en cas d’échec
10. Identification du user correspondant
 Soit l’exemple: exemple_setuid

 Tester la commande: ls -ln exemple_setuid*


 Puis exécuter
 Que remarquez vous?
10. Identification du user correspondant

 Soit l’exemple utilisant l’appel-système setreuid(). Il


permet de fixer les deux UID en une seule fois. Si l’un
des deux UID vaut –1, il n’est pas changé
10. Identification du user correspondant
 Il est possible de modifier également l’UID sauvé,
principalement pour empêcher le retour en arrière comme le
fait setuid()
 il faut définir la constante _GNU_SOURCE avant d’inclure le
fichier d’en-tête <unistd.h>
11. Identification du groupe user correspondant

 Chaque utilisateur du système appartient à un ou


plusieurs groupes définis dans le fichier /etc/groups.
 Un processus appartient donc également aux groupes de
l’utilisateur qui l’a lancé.
 un processus dispose de plusieurs GID (Group Identifier)
• GID réel correspond au groupe principal de
l’utilisateur ayant lancé le programme (celui qui est
mentionné dans /etc/passwd)
• Le GID effectif : peut être différent du GID réel si le
fichier exécutable dispose de l’attribut Set-GID (chmod
g+s).
o utilisé par le noyau pour vérifier les autorisations d’accès aux
fichiers
11. Identification du groupe user correspondant

 Récupération des GID


• gid_t getgid(void);
• gid_t getegid(void);
 Modification des GID
• int setgid(gid_t egid);
• int setegid(gid_t egid);
• int setregid(gid_t rgid, gid_t egid);
o les deux dernières renvoient 0 si elle réussissent et –1 en cas
d’échec
 Les prototypes de ces fonctions sont définit dans
<unistd.h>
 le type gid_t est défini dans <sys/types.h>
11. Identification du groupe user correspondant

 L’ensemble complet des groupes auxquels appartient un


utilisateur est indiqué dans /etc/groups
 Un processus peut obtenir cette liste en utilisant
• int getgroups (int taille, gid_t liste [])
 taille: nombre d’entrées de la table fournie en second
argument.
 getgroups remplit le tableau avec la liste des GID
supplémentaires du processus.
• Si le tableau est trop petit, getgroups() échoue
(renvoie –1 et remplit errno), sauf si la taille est nulle ;
auquel cas, il renvoie le nombre de groupes
supplémentaires du processus
11. Identification du groupe user correspondant

 Exemple d’utilisation de getgroups


11. Identification du groupe user correspondant

 Le nombre maximal de groupes auxquels un utilisateur


peut appartenir est défini dans <asm/param.h> sous le
nom NGROUPS. ( = 32 par défaut)
 Un processus peut fixer sa liste de groupes
supplémentaires
• int setgroups (size_t taille, const gid_t * table);
o n’est utilisable que par root (ou un processus dont le fichier
exécutable est Set-UID root
o le prototype est inclus dans le fichier <grp.h> de la
bibliothèque GlibC 2
o Il faut définir la constante symbolique _BSD_SOURCE pour
avoir accès à cette fonction.
Ne fonctionne que s’il est Set-UID root :
1. $ ls -ln exemple_setgroups*
2. $ ./exemple_setgroups 501 502 503
3. $ su
4. Password:
5. # chown root.root exemple_setgroups
6. # chmod +s exemple_setgroups
7. # exit
8. $ ls -ln exemple_setgroups*
9. $ ./exemple_setgroups 501 502 503

Exemple setgroups
12. Identification du groupe de processus
 Les processus sont organisés en groupes
 Ne pas confondre avec groupes de users
 Les groupes de processus permettent l’envoi global de signaux à
un ensemble de processus.
• Utiles surtout aux shells pour implémenter le contrôle des jobs
• Rarement pris en considération dans les applications classiques
 Déterminer le groupe d’un processus donné:
• pid_t getpgid (pid_t pid);
o déclaré dans <unistd.h>
o renvoie le numéro de groupe, ou –1 si le processus
mentionné n’existe pas,
 Il faut déclarer la constante symbolique _GNU_SOURCE avant
l’inclusion de <unistd.h>
 getpgrp() est similaire à getpgid(0)
• portabilité non assurée entre certaines versions d’Unix
12. Identification du groupe de processus
 Exemple «exemple_getpgid.c»
1. Examiner la liste des processus
présents sur votre système
2. Compiler et exécuter en donnant
en ligne d’arguments la liste des
PID obtenu et finissez par 0
3. Que représente le processus
num 0
12. Identification du groupe de processus
 Un processus peut modifier son propre identifiant de
groupe ou celui de l’un de ses descendants:
• int setpgid (pid_t pid, pid_t pgid);
• pid: PID du processus à modifier
o Nul => il s’agit du processus appelant.
• pgid : nouveau numéro de groupe pour le processus
concerné
o Si (pgid==pid || pgid==0) alors le processus devient leader de
son groupe
• échec si le processus visé n’est ni le processus
appelant ni l’un de ses descendants.
 un processus ne peut plus modifier le groupe de l’un de
ses descendants si celui-ci a effectué un appel à l’une
des fonctions de la famille exec().
12. Identification du groupe de processus

 setpgrp() sert à créer un groupe de processus et à en


devenir leader.
• synonyme de setpgid(0, 0).
• portabilité non assurée
13. Identification de session
 les sessions réunissent divers groupes de processus
 Elles sont très liées à la notion de terminal de contrôle
des processus
 Généralement, une session est attachée à un terminal de
contrôle
• celui qui a servi à la connexion de l’utilisateur
 Au sein d’une session, un groupe de processus est en
avant-plan;
• il reçoit directement les données saisies sur le clavier
du terminal,
• il peut afficher ses informations de sortie sur l’écran de
celui-ci
 Les autres groupes de processus de la session
s’exécutent en arrière-plan
13. Identification de session
 Pour créer une nouvelle session, un processus ne doit pas être leader de
son groupe
• le groupe prend le PID du processus appelant
• ne doit être encore attribué à un groupe qui pourrait contenir d’autres
processus.
 Créer une session:
• pid_t setsid (void);
• déclaré dans <unistd.h>
• renvoie le nouvel identifiant de session
• un nouveau groupe est créé, ne contenant que le processus appelant
(leader).
• une nouvelle session est créée, ne contenant pour le moment que ce
groupe.
• Les descendants du processus leader se trouveront dans cette
nouvelle session.
13. Identification de session
 Pour s’assurer que le processus initial n’est pas leader de
son groupe, on utilise:
• Un processus père exécute un fork(), suivi d’un exit()

• Le processus fils se trouvant dans le même groupe que


son père ne risque pas d’être leader, et peut invoquer
setsid()
 Déterminer l’identifiant de session
• pid_t getsid (pid_t pid);
o n’est déclaré dans <unistd.h> que si la constante
_GNU_SOURCE est définie avant son inclusion
o Echec si le PID transmis ne correspond à aucun processus
existant
o getsid(0) renvoie l’identifiant du processus appelant
o portabilité non assurée
14. Capacités d’un processus

 Les capacités d’un processus = des privilèges


 Un processus dispose de trois ensembles de capacités:
• effectives : utilisé à un instant donné pour vérifier les
autorisations du processus
o rôle similaire à celui de l’UID effectif
• transmissibles : hérité lors d’un appel-système exec()
o le fils a les mêmes privilèges que son père
• possibles : réserve de privilèges
o Un processus peut copier une capacité depuis cet
ensemble vers n’importe lequel des deux autres
14. Capacités d’un processus
 Opérations sur capacités
• mettre dans l’ensemble effectif ou l’ensemble
transmissible n’importe quelle capacité
• supprimer une capacité de n’importe quel ensemble
 Les capacités présentes dans le noyau Linux sont
définies dans <linux/capability.h>
 Pour agir sur les privilèges d’une application
• bibliothèque libcap,
• n’est pas toujours installée dans les distributions
courantes
• Ne pas confondre avec la bibliothèque libpcap, qui
capture des paquets sur le réseau.
Exercice

 Implémenter un programme qui permet de créer un


processus fils et père. Dans le même programme, déclarer
une variable m de type numérique, avant d’accéder aux
zones de code des deux processus.
1) afficher l’adresse et le contenu de la variable dans les
deux processus. qu’est ce que vous remarquez ?
2) Changer le contenu de la variable dans la partie
processus père. Afficher l’adresse et la valeur de la
variable dans les deux processus. qu’est ce que vous
remarquez.
3) Comment se fait la transmission de variable entre les
deux processus
Exercice

 Ecrire un programme qui appel autant de fork()


que nécessaire pour avoir un PID se finissant par
5. Il devra afficher tous les PID intermédiaires, et
une chaine de caractères quand il atteint son but.
Naturellement, il ne doit laisser aucun zombie
derrière lui.

Vous aimerez peut-être aussi