Programmation Système

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

Présentation Chiheb Ameur ABID 2/ 79

Linux

Plan

1 Linux

Programmation Système sous Linux/Unix 2 Les processus

3 Les threads Posix


Dr. Ing. Chiheb Ameur ABID
4 Partage de données entre les threads
Contact: [email protected]

Mars 2023

Présentation Chiheb Ameur ABID 3/ 79 Présentation Chiheb Ameur ABID 4/ 79


Linux Linux

Système d’exploitation ? La naissance d’Unix

Système d’exploitation ?

La naissance d’Unix
➥ New Ken’s System
Z 1969
Z En assembleur
Z Inspiré de Multics
➥ 1971 : réécriture en C
➥ 1975 : large distribution
Présentation Chiheb Ameur ABID 5/ 79 Présentation Chiheb Ameur ABID 6/ 79
Linux Linux

La naissance d’Unix Famille Unix

Famille Unix

Dans les années 1970


➥ AT&T avait le monopole des télécommunications américaines
Z Des fonds disponibles pour divers domaines de recherche
➥ AT&T a développé Unix
Z Elle a offert UNIX gratuitement avec son code source
➥ D’autres organismes ont commencé à utiliser et modifier UNIX
Z BSD (Berkeley System Distribution)
➥ En 1982, AT&T a perdu son monopole
Z Bell labs a commencé par demander des licences pour l’utilisation de UNIX

Présentation Chiheb Ameur ABID 7/ 79 Présentation Chiheb Ameur ABID 8/ 79


Linux Linux

Les logiciels libres ? Gnu is Not Unix

Gnu is Not Unix


➥ Lancé par Richard Stallman en 1983
Z Afin de développer un système d’exploitation entièrement libre
Et un défaut dans une imprimante ! ! ! ➥ Supporté par la FSF depuis 1985
❶ Première version Z Free Software Fondation
✔ Pilote et code source disponible ->Problème corrigé ➥ Créer une suite complète de logiciels
❷ Seconde version Z Mais le noyau tarde à arriver
✖ Pilote en binaire -> Impossible de résoudre le problème Z Projet Hurd, initié en 1990 mais toujours inabouti à ce jour
✖ Il faut attendre jusqu’à la mise à jour de la pilote du constructeur
Présentation Chiheb Ameur ABID 9/ 79 Présentation Chiheb Ameur ABID 10/ 79
Linux Linux

Linux Linux : une philosophie

Linux, enfin

Linux : une philosophie


➥ Modifiable
➥ Basé sur Minix, noyau UNIX pour les PC
développé par Linus Trovalds ➥ Partageable
➥ Fonctionne avec des composants de GNU ➥ Adaptable
adaptés ➥ Ludique
➥ 26 août 1991 : annoncé sur le forum Usenet ➥ Simple
comp.os.minix ➥ Répandu
➥ 1992 : passage à la licence libre GNU GPL

Présentation Chiheb Ameur ABID 11/ 79 Présentation Chiheb Ameur ABID 12/ 79
Linux Linux

Les principales familles de distributions Linux Les distributions Linux

Les principales familles de distributions Linux Les distributions Linux


Présentation Chiheb Ameur ABID 13/ 79 Présentation Chiheb Ameur ABID 14/ 79
Linux Les processus

La norme POSIX ? Plan

1 Linux
La norme POSIX ?
➥ Tous proviennent d’Unix, mais ils commençaient lentement à diverger. 2 Les processus
Gestion des processus
➥ IEEE a lancé le POSIX spécifications en 1988, permettant interopérabilité entre les
Identification des processus
systèmes d’exploitation.
Z POSIX a évolué depuis (la spécification la plus récente en 2017).
3 Les threads Posix
➥ Tous les systèmes d’exploitation POSIX ont des caractéristiques spécifiques au-delà de
POSIX, mais ils partagent la partie POSIX.
4 Partage de données entre les threads
➥ POSIX et "Unix-like" sont parfois utilisé des manière interchangeable.

Présentation Chiheb Ameur ABID 15/ 79 Présentation Chiheb Ameur ABID 16/ 79
Les processus Les processus

Notion de processus Notion de processus

États d’un processus

Notion de processus
➥ Un processus est un programme encours d’exécution
➥ Permet de partager un même matériel entre plusieurs utilisateurs
➥ Isole les programmes
Z Communications simplifiées mais encadrées
Z Sécurité
Z Stabilité (exemple : crash de Firefox ne doit pas gêner LibreOffice)
➥ Notion des années 70, toujours d’actualité
Z Faire des traitements parallèles
Présentation Chiheb Ameur ABID 17/ 79 Présentation Chiheb Ameur ABID 18/ 79
Les processus Les processus

Notion de processus Notion de processus

Notion de processus
➥ Dans le noyau du système d’exploitation, un processus est représenté par une structure de Ordonnancement des processus
données qui comprend : ➥ Dans un système multi-utilisateurs à temps partagé, plusieurs processus peuvent être
Z Un identificateur de processus présents en mémoire centrale en attente d’exécution
Z Un espace de mémoire virtuelle qui contient les instructions du programme et des ➥ Si plusieurs processus sont prêts, le système d’exploitation doit gérer l’allocation du
bibliothèques dynamique, une pile (stack) et un tas (heap) processeur aux différents processus à exécuter. C’est l’ordonnanceur (scheduler) qui
Z Une liste de descripteurs (handle ou descriptor) des différentes ressources systèmes s’acquitte de cette tâche.
(p. ex. les fichiers ouverts) accessibles par le processus.
Z Un jeton de sécurité qui permet au système d’exploitation de déterminer ce que le ➥ Un ordonnanceur fait face à deux problèmes principaux :
processus à le droit de faire. Z Le choix du processus à exécuter ;
Z le temps d’allocation du processeur au processus choisi
➥ Les principaux objectifs d’un ordonnanceur :
Z s’assurer que chaque processus en attente d’exécution reçoive sa part de temps
processeur ;
Z minimiser le temps de réponse ;
Z utiliser le processeur à 100
Z utiliser d’une manière équilibrée les ressources ;
Z prendre en compte les priorités ;
Z être prédictible.

Présentation Chiheb Ameur ABID 19/ 79 Présentation Chiheb Ameur ABID 20/ 79
Les processus Les processus

Commutation du contexte Commutation du contexte

Exécution d’un nouveau processus


Contexte d’un processus
➥ Pour exécuter un nouveau processus, il faut :
➥ Le contexte d’un processus est constitué de
l’ensemble des données qui permettent de reprendre ❶ Sauvegarder le contexte d’unité centrale du processus courant (mot d’état)
l’exécution d’un processus qui a été interrompu ❷ Charger le nouveau mot d’état du processus à exécuter
Z Son état ➥ L’exécution d’un processus s’effectue en deux modes
Z Son mot d’état, en particulier : la valeur des ❶ Mode utilisateur
registres actifs et le compteur ordinal ❷ Mode noyau
Z Les valeurs des variables globales statiques ou
dynamiques
Z Son entrée dans la table des processus
Z Sa zone u : des informations relatives aux droits
d’accès et aux régions mémoires
Z Les piles user et system
Z Les zones de code et de données
Présentation Chiheb Ameur ABID 21/ 79 Présentation Chiheb Ameur ABID 22/ 79
Les processus Les processus
Gestion des processus Gestion des processus

Plan Parallélisme

1 Linux

2 Les processus
Programmation parallèle
Gestion des processus ➥ Il est parfois utile d’exécuter simultanément plusieurs sousprogrammes pour
Identification des processus l’accomplissement d’une tâche.
➥ Il est possible de réaliser ces sous-programmes comme des programmes séparés et de les
3 Les threads Posix exécuter simultanément (p. ex. : scripts CGI).
Notion de threads ➥ Cela présente toutefois certains désavantages :
Modèles de séparation d’un programme en threads
Z La gestion des processus est relativement lourde pour le système.
Gestion des threads
Z Le temps nécessaire au démarrage d’un processus peut être long par rapport au temps
Attributs d’un thread
d’exécution du programme.
Z Les processus sont isolés les uns des autres, l’échange de données ou la
4 Partage de données entre les threads synchronisation entre les processus est mal aisé.
Les mutex
Sémaphore
Variable de condition

Présentation Chiheb Ameur ABID 23/ 79 Présentation Chiheb Ameur ABID 24/ 79
Les processus Les processus
Gestion des processus Gestion des processus

Gestion des processus Gestion des processus

Création d’un processus Terminer un processus


➥ Les primitives de gestion des processus sont définies dans <unistd.h> ➥ Un processus se termine automatiquement lorsqu’il cesse d’exécuter la fonction main()
➥ La primitive fork() permet de créer un processus identique au créateur par copie ➥ Il est possible de terminer explicitement l’exécution du processus courant depuis
Z Le créateur est appelé père (parent process) n’importe quelle fonction :
Z Le créé est appelé fils (child process). 1 void _exit (int status);
2 void exit (int status);
1 pid_t fork(void);
Z status est le code de retour compris entre 0 et 255 à envoyer au système
Z Le PID du processus fils >0 est renvoyé pour le processus parent si OK, sinon -1 d’exploitation. Ce code de retour peut être récupéré depuis le shell à travers la
Z 0 pour le processus fils variable $?
➥ La fonction exit() effectue les opérations suivantes :
Exemple avec fork()
Z Invoquer les routines de terminaisons
Z Fermer les flux d’entrée/sortie
1 #include <stdio.h>
2 int main(void) { Z Invoquer l’appel _exit()
3 int pid;
4 pid=fork();
5 switch (pid) { Avertissement
6 case -1 : printf("Erreur!"); break;
7 case 0 : printf("Je suis le processus fils"); break; Z Un processus qui se termine passe à l’état zombie en attendant que le processus père ait lu
8 default : printf("Je suis le processus père"); break; son code de retour
9 }
10 return 0; Z Si le processus père ne lit pas le code de retour de son fils, celui-ci peut rester indéfiniment
11 } à l’état zombie
Présentation Chiheb Ameur ABID 25/ 79 Présentation Chiheb Ameur ABID 26/ 79
Les processus Les processus
Gestion des processus Gestion des processus

Gestion des processus Gestion des processus

Enregistrer des fonctions de terminaison


Attendre la terminaison d’un processus
➥ Il est possible d’enregistrer des routines de terminaison qui seront invoquées
automatiquement lorsque le processus se terminera normalement ➥ Attendre la terminaison d’un processus fils
Z Il est possible d’enregistrer plusieurs routines 1 pid_t wait(int *status)
Z Les fonctions enregistrées seront invoquées dans l’ordre inverse de leur
enregistrement Z Si le processus courant n’a aucun fils, il retourne -1 avec errno valant ECHILD
Z Si le processus courant a au moins un fils zombie, un zombie est détruit et son pid est
1 #include <stdlib.h>
2 int atexit(void (*routine)(void));
retourné, sinon wait bloque en attendant la mort d’un fils
Z status permet de stocker la raison de la terminaison du processus fils si sa valeur
Z Renvoie 0 si OK, sinon une valeur non nulle est non NULL
Z routine est un pointeur de fonction sur une routine de terminaison

Présentation Chiheb Ameur ABID 27/ 79 Présentation Chiheb Ameur ABID 28/ 79
Les processus Les processus
Gestion des processus Gestion des processus

Gestion des processus Gestion des processus

Lancement d’un programme


Attendre la terminaison d’un processus avec waitpid()
➥ Les appels de la famille exec() permettent de remplacer le programme en cours par un
➥ Une version étendue de wait() autre programme sans changer de numéro de processus (PID)
➥ Attendre la terminaison d’un processus identifié par son PID 1 #include <unistd.h>
2 extern char **environ;
1 pid_t waitpid(pid_t pid, int *status, int options); 3 int execl(const char *path, const char *arg, ...);
4 int execlp(const char *file, const char *arg, ...);
Z status est le code de retour compris entre 0 et 255 à envoyer au système 5 int execle(const char *path, const char *arg,..., char * const envp[]);
6 int execv(const char *path, char *const argv[]);
d’exploitation. Ce code de retour peut être récupéré depuis le shell à travers la 7 int execvp(const char *file, char *const argv[]);
variable $? 8 int execvpe(const char *file, char *const argv[],
9 char *const envp[]);
Présentation Chiheb Ameur ABID 29/ 79 Présentation Chiheb Ameur ABID 30/ 79
Les processus Les processus
Identification des processus Identification des processus

Plan Identifier un processus

PID et PPID
➥ Connaitre son PID
1 Linux
1 pid_t getpid(void);

2 Les processus
➥ Connaitre le PPID
Gestion des processus
Identification des processus 1 pid_t getppid(void);

3 Les threads Posix


Exemple : identifier un processus
Notion de threads
Modèles de séparation d’un programme en threads
1 #include <stdio.h>
Gestion des threads 2 #include <unistd.h>
Attributs d’un thread 3 int main(void){
4 int pid;
5 pid = fork();
4 Partage de données entre les threads 6 if (pid > 0)
7 printf("processus père : %d-%d-%d\n", pid, getpid(), getppid());
Les mutex 8 if (pid == 0) printf("prcessus fils : %d %d %d\n",pid,getpid(),getppid());
Sémaphore 9 if (pid < 0)
Variable de condition 10 printf("Probleme de creation par fork()\n");
11 system("ps -l");
12 return 0;
13 }

Présentation Chiheb Ameur ABID 31/ 79 Présentation Chiheb Ameur ABID 32/ 79
Les processus Les processus
Identification des processus Identification des processus

Identifier un processus Identifier un processus

UID, EUID et SUID


UID et EUID
➥ On distingue trois identifiants d’utilisateur par processus
➥ Connaitre l’UID et l’EUID
Z UID désigne l’identifiant de l’utilisateur réel qui a lancé le processus
Z EUID (Effective UID) désigne l’identifiant de l’utilisateur effectif qui détermine les Z UID désigne l’identifiant de l’utilisateur réel qui a lancé le processus
privilèges d’accès du processus Z EUID (Effective UID) désigne l’identifiant de l’utilisateur effectif qui détermine les
Z SUID (Saved UID) est la copie de l’ancien UID réel quand celui-ci a été modifié par privilèges d’accès du processus
un processus 1 #include <unistd.h>
2 uid_t getuid(void);
➥ Rappel sur la permission Set-UID 3 uid_t geteuid(void);
Z Cette permission concerne uniquement les fichiers exécutables binaires
Z Elle permet à l’utilisateur ayant les droits d’exécution sur ce fichier d’exécuter le Z Ces fonctions renvoient toujours respectivement l’UID et l’EUID
fichier avec les privilèges de son propriétaire
Présentation Chiheb Ameur ABID 33/ 79 Présentation Chiheb Ameur ABID 34/ 79
Les processus Les processus
Identification des processus Identification des processus

Identifier un processus Identifier un processus

UID et EUID
➥ Un processus avec le bit Set-UID démarre avec les privilèges du propriétaire du
Exemple d’affichage l’UID et l’EUID programme
Z Généralement, le propriétaire du programme possède plus de privilèges
1 #include <stdio.h> Z Il est possible de réduire les privilèges en demandant de remplacer l’UID effectif par
2 #include <unistd.h> l’UID réel
3 #include <stdlib.h>
4 1 #include <unistd.h>
5 int main() { 2 /* Définir l’UID effectif du processus appelant. Si cet UID effectif est celui
6 printf("Real UID = %u , Effective UID = %u\n",getuid(),geteuid()); 3 * du superutilisateur, les UID réels et sauvés sont également définis */
7 return EXIT_SUCCESS; 4 int setuid(uid_t uid);
8 } 5
6 /* Définir l’UID effectif du processus appelant. Les processus non privilégiés
➥ Exécution normale 7 * peuvent uniquement définir leur UID effectif à la valeur de leur UID réel,
8 * de leur UID effectif ou de leur UID sauvé. */
9 int seteuid(uid_t euid);
➥ Exécution après l’ajout du bit Set-UID par l’utilisateur root 10
$ sudo chown root Exemple 11 /* Définir les ID d’utilisateur effectif et réel du processus appelant
12 * Les processus non privilégiés peuvent seulement définir leur UID effectif à
$ sudo chmod u+s Exemple la valeur de l’UID réel, de l’UID effectif ou de l’UID sauvé.Les utilisateurs
non privilégiés peuvent seulement définir l’UID réel à la valeur de l’UID réel
ou de l’UID effectif. */
13
14 int setreuid(uid_t ruid, uid_t euid);

Z Renvoie 0 si OK, sinon -1 et met dans errno le code d’erreur

Présentation Chiheb Ameur ABID 35/ 79 Présentation Chiheb Ameur ABID 36/ 79
Les processus Les threads Posix
Identification des processus

Identifier un processus Plan

UID et EUID
➥ Lorsqu’une application s’exécute avec un UID effectif différent de son UID réel, c’est
dans le but de disposer par moment de privilèges auxquels son utilisateur n’a pas droit
directement 1 Linux
➥ Pour limiter les risques d’attaques, il est conseillé de modifier au plus vite l’UID effectif
pour employer l’identité réelle de l’utilisateur 2 Les processus

1 uid_t e_uid_initial;
2 uid_t r_uid; 3 Les threads Posix
3 int main (int argc, char * argv []) { Notion de threads
4 /* Sauvegarde des différents UIDs */
5 e_uid_initial = geteuid (); Modèles de séparation d’un programme en threads
6 r_uid = getuid (); Gestion des threads
7 seteuid (r_uid); /* limitation des droits à ceux du lanceur */ Attributs d’un thread
8 ...
9 fonction_privilegiee ();
10 ...
4 Partage de données entre les threads
11 }
12
13 void fonction_privilegiee (void) {
14 seteuid (e_uid_initial); /* Restitution des privilèges initiaux */
15 ...
16 /* Portion nécessitant les privilèges */
17 ...
18 seteuid (r_uid); /* Retour aux droits du lanceur */
19 }
Présentation Chiheb Ameur ABID 37/ 79 Présentation Chiheb Ameur ABID 38/ 79
Les threads Posix Les threads Posix
Notion de threads Notion de threads

Plan Parallélisme vs concurrence

1 Linux

2 Les processus Notion de thread


Gestion des processus
Identification des processus ➥ Un thread est un fil d’exécution qui représente l’exécution d’une séquence d’instruction.
➥ À la création d’un processus, le système d’exploitation crée automatiquement un thread
3 Les threads Posix
qui démarre au point d’entrée du programme (fonction main).
Notion de threads ➥ L’ordonnanceur (scheduler) du système d’exploitation partage les ressources CPU entre
Modèles de séparation d’un programme en threads les différents threads.
Gestion des threads ➥ Les systèmes d’exploitation modernes permettent de créer des threads supplémentaires
Attributs d’un thread dans un même processus pour exécuter plusieurs sous-programmes simultanément.
Z Le programmeur est responsable de la création de threads supplémentaires.
4 Partage de données entre les threads
Les mutex
Sémaphore
Variable de condition

Présentation Chiheb Ameur ABID 39/ 79 Présentation Chiheb Ameur ABID 40/ 79
Les threads Posix Les threads Posix
Notion de threads Notion de threads

Parallélisme vs concurrence Parallélisme vs concurrence

Processus vs Thread
Processus vs Thread
➥ Processus (lourd)
Z Contient tout ce qui est nécessaire à l’exécution (registre du processeur, ressources,
mémoire, etc.)
Z Communication uniquement via des canaux dédiés (IPC) : Signaux, Tubes, Memory
Map, Sockets, etc.
Z Commutation de contexte lente
➥ Thread (processus léger)
Z Un processus contient un ou plusieurs threads
Z Chaque thread a son propre compteur programme, sa propre pile
Z Ces threads partagent les mêmes ressources, la même mémoire
Z Commutation de contexte plus rapide
Z Communications = partage de variables ⇒ Accès concurrents
Présentation Chiheb Ameur ABID 41/ 79 Présentation Chiheb Ameur ABID 42/ 79
Les threads Posix Les threads Posix
Notion de threads Modèles de séparation d’un programme en threads

Programmation concurrentielle Plan

1 Linux

Les threads 2 Les processus


➥ Programmation concurrente Gestion des processus
Identification des processus
Z Travailler sur plusieurs tâches à la fois
➥ Un thread (tâche) représente (généralement) une fonction (une méthode) en cours
3 Les threads Posix
d’exécution
Notion de threads
➥ Un processus peut contenir un ou plusieurs threads. Ces threads partagent alors la Modèles de séparation d’un programme en threads
mémoire ainsi que diverses autres ressources Gestion des threads
Z Deux threads qui veulent collaborer peuvent le faire par l’intermédiaire de variables Attributs d’un thread
partagées.
Z Le contexte d’un thread est léger par rapport à un processus
4 Partage de données entre les threads
Les mutex
Sémaphore
Variable de condition

Présentation Chiheb Ameur ABID 43/ 79 Présentation Chiheb Ameur ABID 44/ 79
Les threads Posix Les threads Posix
Modèles de séparation d’un programme en threads Modèles de séparation d’un programme en threads

Modèles de séparation d’un programme en threads Modèles de séparation d’un programme en threads

Le modèle délégation
➥ Un seul thread, le patron, accepte les entrées pour l’ensemble du programme
Z Sur la base de cette entrée, le patron transmet des tâches spécifiques à un ou plus aux
threads de travail
➥ Le patron crée chaque thread de travail, lui attribue des tâches et, si nécessaire, attend qu’il
Comment décomposer un programme en threads ? se termine
➥ Comment décomposer un programme en plusieurs threads ? ➥ Il est important que vous minimisez la fréquence à laquelle le patron et ouvriers
communiquent.
➥ Il existe plusieurs modèles
Z Le modèle délégation (boss-worker model ou delegation model)
Z Le modèle pair (peer model)
Z Le modèle pipeline (pipeline model)
Présentation Chiheb Ameur ABID 45/ 79 Présentation Chiheb Ameur ABID 46/ 79
Les threads Posix Les threads Posix
Modèles de séparation d’un programme en threads Modèles de séparation d’un programme en threads

Modèles de séparation d’un programme en threads Modèles de séparation d’un programme en threads

Le modèle pair
➥ Tous les threads travaillent simultanément sur leurs tâches sans leader.
➥ Un seul thread doit créer tous les autres threads homologues au démarrage du programme.
Z Ce thread agit ensuite comme un autre thread, ou se suspend en attendant les autres Le modèle pipeline
pairs finir.
➥ Le modèle de pipeline suppose
➥ Le modèle de pair convient aux applications qui ont un ensemble fixe et bien défini
Z Un long flux d’entrée
d’entrées
Z Une série de sous-opérations (appelées étapes ou filtres) à travers lesquelles chaque
unité d’entrée doit être traitée.
Z Chaque étape de traitement peut gérer une unité d’entrée différente à la fois.

Présentation Chiheb Ameur ABID 47/ 79 Présentation Chiheb Ameur ABID 48/ 79
Les threads Posix Les threads Posix
Modèles de séparation d’un programme en threads Modèles de séparation d’un programme en threads

Programmation concurrentielle Programmation concurrentielle

Généralités sur l’interface Pthreads


POSIX ? ➥ Trois grandes catégories de fonctions / types de données
➥ POSIX : Portable Operating System Interface for UNIX ❶ Gestion des threads
➥ Avant le POSIX Z Créer des threads, les arrêter, contrôler leurs attributs, etc.
Z Chaque OS possède sa propre API pour gérer les threads ❷ Synchronisation par mutex (mutual exclusion)
Z Difficile d’écrire des programmes multi-threadé :
Z Créer, détruire verrouiller, déverrouiller des mutex ; Contrôler leurs attributs
➥ Après
❸ Variables de condition
Z POSIX (IEEE 1003.1c-1995) offre un standard pour la gestion des threads
Z Communications entre threads partageant un mutex
Z Les créer, les détruire, attendre dessus, les signaler ; Contrôler leurs attributs
Présentation Chiheb Ameur ABID 49/ 79 Présentation Chiheb Ameur ABID 50/ 79
Les threads Posix Les threads Posix
Modèles de séparation d’un programme en threads Gestion des threads

Programmation concurrentielle Plan

1 Linux

2 Les processus
Gestion des processus
Généralités sur l’interface Pthreads Identification des processus
➥ Types de données sont structures opaques, fonctions d’accès spécifiques
➥ L’interface compte 60 fonctions, nous ne verrons pas tout 3 Les threads Posix
Notion de threads
➥ Il faut charger le fichier d’entête pthread.h dans les sources Modèles de séparation d’un programme en threads
➥ Il faut spécifier l’option -pthread à gcc Gestion des threads
Attributs d’un thread

4 Partage de données entre les threads


Les mutex
Sémaphore
Variable de condition

Présentation Chiheb Ameur ABID 51/ 79 Présentation Chiheb Ameur ABID 52/ 79
Les threads Posix Les threads Posix
Gestion des threads Gestion des threads

Gestion des threads Gestion des threads

Créer un thread Terminer un thread


➥ Créer un nouveau thread ➥ Terminer le thread appelant
1 int pthread_create(pthread_t *restrict thread,const pthread_attrt *restrict attr, 1 void pthread_exit(void *value ptr)
2 void *(*start routine)(void*), void *restrict arg);

Z Si attr est NULL, les attributs par défaut seront utilisés


Z Si attr est NULL, les attributs par défaut seront utilisés
Z En cas de réussite, pthread_create() stocke l’ID du thread créé dans
Z En cas de réussite, pthread_create() stocke l’ID du thread créé dans
l’emplacement référencé par thread
l’emplacement référencé par thread
Présentation Chiheb Ameur ABID 53/ 79 Présentation Chiheb Ameur ABID 54/ 79
Les threads Posix Les threads Posix
Gestion des threads Gestion des threads

Gestion des threads Gestion des threads

Attendre la terminaison d’un thread Détacher un thread

➥ Attendre la fin d’un thread ➥ Terminer le thread appelant


1 int pthread_detach(pthread_t thread)
1 int pthread_join(pthread_t thread, void **value ptr)

Z Le thread A joint le thread B : A bloque jusqu’à la fin de B Z Détacher un thread revient à dire que personne ne le joindra à sa fin
Z Utile pour la synchronisation (rendez-vous) Z Le système libère ses ressources au plus vite
Z Second argument reçois un pointeur vers la valeur retour du pthread_exit() Z Evite les threads zombies quand on ne veut ni synchroniation, ni code de retour ´
Z On ne peut pas ré-attacher un thread détaché

Présentation Chiheb Ameur ABID 55/ 79 Présentation Chiheb Ameur ABID 56/ 79
Les threads Posix Les threads Posix
Attributs d’un thread Attributs d’un thread

Plan Attributs d’un threads

1 Linux

Attributs d’un threads


2 Les processus
➥ Les attributs d’un threads sont représentés par la structure pthread_attr_t
Gestion des processus
Identification des processus Z Il s’agit d’une structure opaque : il ne faut faire ni affectation, ni affectation, ni
comparaison directe
3 Les threads Posix ➥ La structure doit être initialisée avant son utilisation
Notion de threads 1 int pthread_attr_init(pthread_attr_t * attributs)
Modèles de séparation d’un programme en threads
Gestion des threads Z Il s’agit d’une structure opaque : il ne faut faire ni affectation, ni affectation, ni
Attributs d’un thread comparaison directe
➥ La libération de l’objet des attributs
4 Partage de données entre les threads 1 int pthread_attr_destroy(pthread_attr_t * attributs)
Les mutex
Sémaphore
Variable de condition
Présentation Chiheb Ameur ABID 57/ 79 Présentation Chiheb Ameur ABID 58/ 79
Partage de données entre les threads Partage de données entre les threads

Plan Partage de données

1 Linux
Modèle de mémoire partagée
2 Les processus ➥ Tous les threads ont accès à la même mémoire
partagée globalement
3 Les threads Posix ➥ Les données peuvent être partagées ou privées
➥ Les données partagées sont accessibles par tous les
4 Partage de données entre les threads threads
Les mutex
Sémaphore ➥ Les données privées ne peuvent être accédées que par
Variable de condition les threads qui les possèdent
➥ Synchronisation explicite

Présentation Chiheb Ameur ABID 59/ 79 Présentation Chiheb Ameur ABID 60/ 79
Partage de données entre les threads Partage de données entre les threads

Partage de données entre les threads Partage de données entre les threads

Partage des données Section critique


➥ Toute variable créée avant la création du thread et accessible depuis un ou plusieurs ➥ Partie d’un thread dont l’exécution ne doit pas entrelacer avec d’autres threads
threads est une variable partagée
Z Indivisibilité de la section critique
Z Les variables globales sont des variables partagées
Z Les variables locales à la fonction associée à un thread ne sont pas partagées ➥ Une fois un thread entre dans la section critique
➥ Le spécificateur de stockage thread_local permet à plusieurs threads d’utiliser le Z Le thread qui entre dans la SC doit terminer son travail en empêchant les autres
stockage local via un point d’accès global. threads de jouer sur les mêmes données
Z La section critique doit être verrouillée afin de devenir indivisible
Z Avec thread_local une variable globale devient une variable locale au thread
Présentation Chiheb Ameur ABID 61/ 79 Présentation Chiheb Ameur ABID 62/ 79
Partage de données entre les threads Partage de données entre les threads
Les mutex

Partage de données entre les threads Plan

1 Linux

2 Les processus
Problème de section critique Gestion des processus
Identification des processus
➥ Lorsqu’un thread manipule une donnée (ressource) partagée avec d’autres, nous disons
qu’il se trouve dans une section critique
3 Les threads Posix
➥ Le problème de la SC est de trouver un algorithme d’exclusion mutuelle de threads
Notion de threads
Z Les résultats de leurs actions ne dépend pas de l’ordre de leur entrelacement Modèles de séparation d’un programme en threads
➥ L’exécution de la section critique doit être mutuellement exclusive et indivisible Gestion des threads
Z Un seul thread exécute la SC Attributs d’un thread

4 Partage de données entre les threads


Les mutex
Sémaphore
Variable de condition

Présentation Chiheb Ameur ABID 63/ 79 Présentation Chiheb Ameur ABID 64/ 79
Partage de données entre les threads Partage de données entre les threads
Les mutex Les mutex

Les mutex Les mutex

Utilisation d’un mutex


➥ L’utilisation typique d’un mutex pour assurer l’accès en exclusion mutuelle à une SC
Z Créer et initialiser une variable du mutex
Z Plusieurs threads tentent de vérouiller le mutex avant d’entrer dans la section critique
Z Seulement un thread réussit et prend le mutex, les autres sont bloqués ⇒ le mutex est
Coordination par les mutex
vérouillé
➥ Un mutex (mutual exclusion) est une structure de données qui permet de contrôler l’accès Z Le thread propriétaire du mutex effectue un ensemble d’actions dans la section
à une ressource critique
➥ Un mutex qui contrôle une ressource peut se trouver dans deux états Z Le thread propriétaire dévrouille le mutex en quittant la section critique
Z Un seul parmi les threads bloqués est réveillé, et il prend le contrôle mutex en
❶ Libre (unlocked) : indique que la ressource est libre et peut être utilisée sans risquer
répétant le processus
de provoquer une violation d’exclusion mutuelle
❷ Réservée (locked) : indique que la ressource associée est actuellement utilisée et
qu’elle ne peut pas être utilisée par un autre thread
Présentation Chiheb Ameur ABID 65/ 79 Présentation Chiheb Ameur ABID 66/ 79
Partage de données entre les threads Partage de données entre les threads
Les mutex Les mutex

Les mutex Les mutex

Création et destruction d’un mutex Verouillage/Déverouillage d’un mutex


➥ Type de donnée d’un mutex : pthread_mutex_t ➥ Bloquer le thread courant si le mutex est verouillé par un autre thread, sinon verouiller le
➥ Création mutex
Z Statique 1 int pthread_mutex_lock(pthread_mutex_t *mutex);

1 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ; Z Renvoie 0 si OK, sinon un code d’erreur


Z Dynamique Z mutex est le mutex à verrouiller

1 pthread_mutex init(pthread_mutex_t *, pthread_mutexattr_t *) ;


➥ Tenter de verrouiller un mutex sans bloquer le thread courant
1 int pthread_mutex_trylock(pthread_mutex_t *mutex);
➥ Destruction
Z Renvoie 0 si le mutex a été bien verrouillé, sinon l’erreur EBUSY
1 int pthread_mutex_destroy(pthread_mutex_t *mutex);
➥ Libérer un mutex
Z Le mutex doit être déverrouillé avant sa destruction 1 int pthread_mutex_unlock(pthread_mutex_t *mutex);
Z Retourne 0 en cas de succès, sinon un code d’erreur

Présentation Chiheb Ameur ABID 67/ 79 Présentation Chiheb Ameur ABID 68/ 79
Partage de données entre les threads Partage de données entre les threads
Les mutex Sémaphore

Les mutex Plan

Exemple d’utilisation des mutex 1 Linux

1 #include <pthread.h> 2 Les processus


2
3 pthread_mutex_t count_mutex; Gestion des processus
4 long long count; Identification des processus
5
6 void increment_count() {
7 pthread_mutex_lock(&count_mutex); 3 Les threads Posix
8 count = count + 1;
9 pthread_mutex_unlock(&count_mutex); Notion de threads
10 } Modèles de séparation d’un programme en threads
11
Gestion des threads
12 long long get_count()
13 { Attributs d’un thread
14 long long c;
15 pthread_mutex_lock(&count_mutex);
16 c = count; 4 Partage de données entre les threads
17 pthread_mutex_unlock(&count_mutex); Les mutex
18 return (c);
19 } Sémaphore
Variable de condition
Présentation Chiheb Ameur ABID 69/ 79 Présentation Chiheb Ameur ABID 70/ 79
Partage de données entre les threads Partage de données entre les threads
Sémaphore Sémaphore

Sémaphore Sémaphore

Création d’un sémaphore nommé

Présentation ➥ Un sémaphore peut être partagé entre plusieurs processus


➥ Créer un sémaphore nommé
➥ Sémaphores généralisent les verrous
1 sem_t *sem_open(char *name, int flags);
➥ Inventés par Dijkstra à la fin des années 1960 2 sem_t *sem_open(char *name, int flags, mode_t mode,unsigned int value);
➥ Principale primitive de synchronisation à l’origine dans UNIX
Z Renvoie 0 si OK, sinon un code d’erreur
➥ Définition : un sémaphore est un entier non négatif qui a deux opérations
Z name : le nom du sémaphore
Z P() : opération atomique qui attend que le sémaphore soit positif et le décrémente de Z value : valeur initiale du sémaphore. Par défaut 1.
1. Proberen (tester en néerlandais) = puis-je ? Z flags : Seulement quelques valeurs possibles de flags parmi celles du open :
Z V() : opération atomique qui incrémente le sémaphore de 1, et réveille les O_CREAT et O_EXCL pour flags
threads/processus bloquant sur P(). Verhogen (incrémente en néerlandais) = vas-y
➥ Libérer un sémaphore
1 int sem_close(sem_t *s);

Présentation Chiheb Ameur ABID 71/ 79 Présentation Chiheb Ameur ABID 72/ 79
Partage de données entre les threads Partage de données entre les threads
Sémaphore Sémaphore

Sémaphore Sémaphore

Création d’un sémaphore anonyme


➥ Un sémaphore anonyme ne peut être utilisé que par les threads d’un même processus Contrôler un sémaphore
➥ Créer un sémaphore anonyme ➥ Incrémenter un sémaphore : l’opération V()
1 int sem_init(sem_t *sem, int pshared, unsigned int value); 1 int sem_post(sem_t *s);

Z Renvoie 0 si OK, sinon un code d’erreur Z Renvoie 0 si OK, sinon un code d’erreur
Z name : le nom du sémaphore ➥ Décrémenter un sémaphore : l’opération P() et bloque le thread si nécessaire
Z value : valeur initiale du sémaphore. Par défaut 1.
Z flags : Seulement quelques valeurs possibles de flags parmi celles du open : 1 int sem_wait(sem_t *s);

O_CREAT et O_EXCL pour flags


Z Bloque si la valeur est <= 0. Le processus est débloqué si la valeur > 0. Retourne -1 si
➥ Libérer un sémaphore erreur.
1 int sem_destroy(sem_t *sem);
Présentation Chiheb Ameur ABID 73/ 79 Présentation Chiheb Ameur ABID 74/ 79
Partage de données entre les threads Partage de données entre les threads
Variable de condition Variable de condition

Plan Variable de condition

1 Linux

2 Les processus
Gestion des processus Présentation
Identification des processus ➥ Attendre (sans CPU) qu’un autre thread ait réalisé un traitement
➥ Notifier les autres threads quand un travail est terminé
3 Les threads Posix Z Coopération entre les threads !
Notion de threads
Modèles de séparation d’un programme en threads ➥ Nécessite la mise en place de variables partagées
Gestion des threads Z Pour indiquer la fin d’un traitement
Attributs d’un thread Z Pas d’attente active
Z Donc, basée sur l’utilisation de mutex
4 Partage de données entre les threads
Les mutex
Sémaphore
Variable de condition

Présentation Chiheb Ameur ABID 75/ 79 Présentation Chiheb Ameur ABID 76/ 79
Partage de données entre les threads Partage de données entre les threads
Variable de condition Variable de condition

Variable de condition Variable de condition

Présentation
➥ En C, les variables de conditions sont représentées par le type pthread_cond_t
Principe d’utilisation d’une variable de condition
➥ Principe de fonctionnement
Z Un thread reste bloqué jusqu’à que la condition spécifiée par la variable de condition ➥ Une variable de condition est toujours associée à un mutex
soit réalisée Z Éviter les problèmes d’accès concurrents à la variable
Z Un autre thread sert à signaler que la condition a été bien remplie ➥ Le thread qui doit attendre une condition
➥ Avant son utilisation, une variable de condition doit être initialisée Z Initialise la variable et le mutex qui lui est associé
Z Initialisation statique Z Bloque le mutex , puis se mettre en attente de la réalisation de la condition
Z Libère le mutex
1 pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
➥ Le thread réalisant la condition
Z Initialisation dynamique Z Travaille jusqu’à réaliser la condition
1 int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *cattr); Z Bloque le mutex associé à la condition
Z Envoie un signal pour montrer que la condition est remplie
L’argument cattr n’a pas d’utilité et il est fixé à NULL Z Libère le mutex
➥ Une variable de condition inutilisée est libérée avec pthread_cond_destroy()
1 int pthread_cond_destroy(pthread_cond_t *cond);
Présentation Chiheb Ameur ABID 77/ 79 Présentation Chiheb Ameur ABID 78/ 79
Partage de données entre les threads Partage de données entre les threads
Variable de condition Variable de condition

Variable de condition Variable de condition

Signaler la réalisation d’une condition


Mise en attente sur une variable de condition
➥ Signaler la réalisation d’une condition à un seul thread bloqué : un seul thread sera réveillé
➥ Mise en attende d’un thread sur une variable de condition
1 int pthread_cond_signal(pthread_cond_t *cond);
1 int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
➥ Signaler la réalisation d’une condition à tous les threads bloqués : tous les threads seront
Z Renvoie 0 si OK, sinon le code de l’erreur réveillés
Z Bloque le mutex associé à la condition
1 int pthread_cond_broadcast(pthread_cond_t *cond);
Z cond est la variable de condition
Z mutex est le mutex associé à la variable de condition Z Renvoie 0 si OK, sinon le code de l’erreur
Z cond est la variable de condition
Exemple
Exemple
1 void foo () {
2 pthread_mutex_lock(&verrou);
3 while (done == 0) 1 void bar() {
4 pthread_cond_wait (&varcond,&verrou); 2 pthread_mutex_lock(&verrou);
5 pthread_mutex_unlock(&verrou); 3 done = 1;
6 } 4 pthread_cond_signal (&varcond);
5 pthread_mutex_unlock(&verrou);
6 }

Présentation Chiheb Ameur ABID 79/ 79


Partage de données entre les threads
Variable de condition

M ERCI POUR VOTRE ATTENTION

Questions ?

Vous aimerez peut-être aussi