Académique Documents
Professionnel Documents
Culture Documents
Système d’exploitation
Module: M18 - IRISI S3
FST Marrakech
Université Cadi Ayyad
Gestion de thread
Processus : rappel
Unité de calcul
I dont les caractéristiques sont stockées dans un PCB
I possédant un espace mémoire propre
Notion de thread
Définition
Thread ("processus léger") : unité d’exécution rattachée à un processus
(interne à un processus), chargée d’exécuter une partie du processus.
Notion de thread
Vitesse d’exécution
I Traiter un lot de données, lire le suivant
Processus mono-thread
Un processus mono-thread est un programme qui s’exécute selon un
chemin unique (Compteur Ordinal ).
On dit qu’il a un flot de contrôle unique (un seul thread).
Processus multi-thread
De nombreux systèmes d’exploitation modernes offrent la possibilité
d’associer à un même processus plusieurs chemins d’exécution.
On parle du multi-thread qui permet d’exécuter simultanément des parties
d’un même processus.
Chaque partie correspond à un chemin d’exécution du processus.
Processus multi-thread
Avantages du multi-threading
L’ensemble de tous les threads créés est enregistré dans une table appelé
«table des threads».
Types de thread
L’implémentation des liens entre les threads utilisateurs et les threads noyaux
varie considérablement d’une plateforme à une autre. On distingue trois modèles
de multi-threading :
Plusieurs-vers-un : plusieurs threads utilisateur vers un thread noyau
Un-vers-un : un thread utilisateur vers un thread noyau
Plusieurs-vers-plusieurs : plusieurs threads utilisateur vers plusieurs threads
noyau
Thread utilisateur
Les threads utilisateur sont implantés dans une bibliothèque logicielle
(niveau utilisateur ) qui fournit un support pour les gérer.
I Ex. Les threads Java sont gérés par la machine virtuelle Java (JVM).
Les threads utilisateur ne sont pas gérés par le noyau; Le noyau gère les
processus (table des processus) et ne se préoccupe pas de l’existence des
threads
I Lorsque le noyau alloue le processeur à un processus, le temps d’allocation du
processeur est réparti entre les différents threads du processus (cette
répartition n’est pas gérée par le noyau).
Thread utilisateur
Avantages
I Les threads utilisateur sont généralement créés, et gérés rapidement.
I Ordonnancement géré par l’application : flexibilité.
I Ils facilitent la portabilité (Indépendants de système d’exploitation).
Inconvénients
I À tout instant, au plus un thread par processus est en cours d’exécution. Cette
implémentation n’est pas intéressante pour des systèmes multiprocesseurs.
I Si un thread d’un processus se bloque, tout le processus est bloqué. Pour
pallier cet inconvénient, certaines librairies transforment les appels système
bloquants en appels système non bloquants.
Thread noyau
Les threads noyau sont directement supportés par le système
d’exploitation qui se charge de leur gestion.
I Ex. Linux ne fait pas de distinction entre les processus et les threads qui sont
communément appelés tâches.
Ordonnacement directement géré par le noyau.
I Il est donc nécessaire de disposer d’une table des threads pour mémoriser les
contextes d’exécution et les informations de chaque thread.
Affectation du CPU fait sur base des threads.
I Un temps CPU est alloué à chaque thread
Thread noyau
Avantages
I Si un thread d’un processus est bloqué, un autre thread du processus peut
être élu par le noyau.
I Un processus peut ajuster les niveaux de priorité de ses threads. Par exemple,
un processus peut améliorer son interactivité en assignant : une forte priorité
à un thread qui traite les requêtes des utilisateurs et une plus faible priorité
aux autres.
I Différents threads peuvent être répartis sur plusieurs cœurs, Cette
implémentation est plus intéressante pour les systèmes multiprocesseurs.
Inconvénients
I Performance (gestion plus coûteuse)
I Le changement de contexte nécessite de passer par le noyau
I Les programmes utilisant les threads noyau sont moins portables que ceux qui
utilisent des threads utilisateur.
Exemples :
I Solaris Green Threads
I GNU Portable Threads
Exemples :
I Windows NT/2000/XP
I OS/2
I Linux
I Solaris 9 et suivants
Exemples :
I Solaris avant version 9
I Windows NT/2000 (avec
ThreadFiber )
Inconvénient : mise en œuvre plus
complexe
Librairie de thread
Pthread
(POSIX Thread)
Introduction
La norme POSIX
La norme POSIX est l’acronyme Portable Operating System Interface for
uniX ou interface portable pour les systèmes d’exploitation.
Elle a initialement été mise en place pour les systèmes de type UNIX mais
d’autres systèmes d’exploitation comme Linux, macOS, Solaris et
Windows sont aujourd’hui conformes à POSIX.
La norme POSIX
I l’ordonnancement
I les signaux en temps réel
I les horloges et les timers
I les sémaphores
I le passage de messages
I la mémoire partagée
I les entrées-sorties synchrones et asynchrones
I les outils de verrouillage de la mémoire
Un pthread :
est identifié par un identificateur unique TID (Thread Identifier).
exécute une fonction passée en paramètre lors de sa création.
possède des attributs.
peut se terminer (pthread_exit) ou être annulé par un autre thread
(pthread_cancel).
peut attendre la fin d’un autre thread (pthread_join)
Logigramme
Exemple 1
# include < stdio .h >
# include < pthread .h >
void * fct ( void * arg )
{
printf ( " Je suis le thread % lu \ n " , pthread_self () ) ;
printf ( " J ai recu l ’ argument % s \ n " , ( char *) arg ) ;
}
int main ()
{
pthread_t thd ;
printf ( " Le processus % d lance un thread \ n " , getpid () ) ;
if ( p thread_create (& thd , NULL , fct , " BONJOUR " ) )
perror ( " pthread_create \ n " ) ;
else
pthread_join ( thd , NULL ) ;
return 0;
}
Lorsqu’un thread crée un autre thread, s’il ne lui est pas explicitement
indiqué d’attendre la fin d’exécution du thread fils, alors à sa terminaison il
forcera l’arrêt du thread fils.
Pour éviter cela, on utilise la fonction pthread_join:
void pthread_join(pthread_t thd_id, void**statut)
I thd_id : représente l’identificateur du thread que le thread créateur doit
attendre.
I statut sert à récupérer la valeur de retour et l’état de terminaison. Il vaut
NULL si le thread ne renvoie aucune valeur.
I Le thread thd_id doit appartenir au même processus que le thread appelant.
I Si le thread thd_id n’est pas encore terminée, le thread appelant sera bloqué
jusqu’à ce que le thread thd_id se termine.
I Si le thread thd_id est déjà terminée, le thread appelant n’est pas bloquée.
I Le thread thd_id doit être joignable.
I Un seul thread réussit l’appel.
I Les ressources de thread sont alors libérées.
Exemple 2 :
Exemple 2
int main ()
{
int i ;
pthread_t thA , thB ;
printf ( " Creation du thread A \ n " ) ;
pthr ead_create (& thA , NULL , threadA , NULL ) ;
printf ( " Creation du thread B \ n " ) ;
pthr ead_create (& thB , NULL , threadB , NULL ) ;
usleep (1000000) ;
// attendre que les threads aient termine
printf ( " Le thread principal attend que les autres se terminent \ n " ) ;
pthread_join ( thA , NULL ) ;
pthread_join ( thB , NULL ) ;
exit (0) ;
}
Exemple 2 (Cont...)
void * threadC ( void * inutilise )
void afficher ( int n , char
{
lettre )
afficher (150 , ’C ’ ) ;
{
printf ( " \ n Fin du thread C \ n " ) ;
int j ;
pthread_exit ( NULL ) ;
for ( j =1; j < n ; j ++)
}
{
usleep (1000000) ;
void * threadB ( void * inutilise )
printf ( " % c " , lettre ) ;
{
}
pthread_t thC ;
}
printf ( " Creation du thread C \ n " ) ;
pth read_c reate (& thC , NULL , threadC , NULL ) ;
void * threadA ( void * inutilise )
afficher (100 , ’B ’ ) ;
{
printf ( " \ n Le thread B attend la fin du
afficher (100 , ’A ’ ) ;
thread C \ n " ) ;
printf ( " \ n Fin du thread
pthread_join ( thC , NULL ) ;
A\n");
printf ( " \ n Fin du thread B \ n " ) ;
pthread_exit ( NULL ) ;
pthread_exit ( NULL ) ;
}
}
Il peut arriver que dans une application multitâche, on n’ait pas besoin que le
processus (le thread principal) attende la fin d’exécution d’un thread annexe
avant de se terminer.
Pour cela, on force le thread annexe à être détaché de son processus.
I Lors de la création :
pthread_attr_t attr ;
p t hre ad_ att r_ ini t (& attr ) ;
p t h r e a d _ a t t r _ s e t d e t a c h s t a t e (& attr , P T H R E A D _ C R E A T E _ D E T A C H E D ) ;
pthread_create ( tid , & attr , func , NULL ) ;