3IS - Système d`exploitation linux - Threads - Etis

Transcription

3IS - Système d`exploitation linux - Threads - Etis
3IS - Système d'exploitation linux
Threads
2010 – David Picard
Contributions de : Arnaud Revel, Mickaël Maillard
[email protected]
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Qu'est-ce qu'un thread ?
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Quel intérêt ?
●
●
●
Contexte multi-processeurs
Programmation événementielle (interfaces
graphiques, par exemple)
Plus léger
–
Moins de charge pour créer, ordonnancer et détruire un
thread
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Propriétés
●
Invisibles en dehors du processus créateur
●
Communication plus facile entre threads
●
Plusieurs threads peuvent exécuter le même
code
–
Parallélisation des routines
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Scénarios possibles
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Différentes implantations
●
●
La programmation en threads est régie par la
norme Posix
Il existe cependant plusieurs implantations
différentes
–
–
–
Threads en espace utilisateur : GNU Pth
Implantation mixte : SunOS/proposition Linux rejetée
Threads en mode noyau : Linux
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Threads en user space
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Threads en user space
●
●
●
●
●
Le noyau n'a pas connaissance de l'existance des
threads
Une bibliothèque en user space se charge de
gérer les threads
La communication entre threads ne passe pas par
le noyau
L'ordonnancement des threads, assuré par la
bibliothèque, est spécifique à un processus
Le noyau continue d'ordonnancer les processus
indépendamment des threads
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Implantation mixte
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Propriétés
●
●
●
●
La création et l'ordonnancement sont faits en
espace utilisateur
Le programmeur peut définir directement ou
indirectement le nombre de threads noyaux
Le noyau créé autant de processus légers
(LWP – LightWeight Process) que de threads
noyaux
Chaque LPW peut gérer plusieurs threads
utilisateurs
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Avantages et inconvéniants
●
Avantages
–
–
–
●
On limite les appels systèmes
On peut choisir l'algorithme do'rdonnancement des threads
Rend les programmes portables sur d'autres systèmes
disposant d'une API de threads en user space
Inconvéniants
–
–
Les appels systèmes étant bloquant, tous les threads sont
bloqués
Le noyau peut assigner un processus à un processeur,
mais tous les threads de ce processus seront assignés à
ce processeur
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Threads en espace noyau
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Propriétés des threads noyaux
●
Gestion assurée par le noyau
●
Pas d'API spéciale
●
●
●
Le noyau doit maintenir un contexte
d'information sur les threads et les processus
La commutation entre threads se fait par le
noyau
L'ordonnancement est fonction des threads
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Avantages et inconvéniants
●
Avantages
–
–
●
Le noyau peut assigner plusieurs threads d'un même
processus sur différents processeurs
Les appels système ne bloquent pas les autres threads
Inconvéniants
–
La commutation entre threads nécéssite un passage en
mode noyau, donc une perte de performances
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Linux
Sous linux, les threads sont gérés comme des
processus à part entière dans le noyau
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Exemple
#include <pthread.h> /* Compilation avec -lpthread */
void
*routine_thread(void *data)
{
int
id;
int
status = 0;
id = *((int *)data);
fprintf(stdout, "Bonjour, je suis la thread %i\n", id);
pthread_exit(&status);
}
int
main(int ac, char **av)
{
pthread_t
tid1;
pthread_t
tid2;
int
id1 = 1;
int
id2 = 2;
int
*status = NULL;
pthread_create((pthread_t *)&tid1, NULL, routine_thread, (void *)&id1);
pthread_create((pthread_t *)&tid2, NULL, routine_thread, (void *)&id2);
pthread_join(tid2, (void **)&status);
fprintf(stdout, "La thread %i est terminee avec le status %i\n", id2, *status);
pthread_join(tid1, (void **)&status);
fprintf(stdout, "La thread %i est terminee avec le status %i\n", id1, *status);
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Exclusion mutuelle
●
●
●
●
Les threads peuvent se partager les mêmes ressources au sein
du processus
Il est donc nécessaire d'entrer en section critique avant d'utiliser
une ressource partagée
Les threads fournissent des primitives d'exclusion mutuelle : les
mutex
Les fonctions associées sont :
–
–
–
–
–
pthread_mutex_init : initialise la mutex
pthread_mutex_lock : essaye de prendre le mutex. S’il est deja pris par un
autre thread, alors l’appel reste bloquant jusqu’à sa liberation
pthread_mutex_trylock : essaye de prendre le mutex. S’il est déjà pris par un
autre thread, alors l’appel ne bloque pas
pthread_mutex_unlock : libère un mutex qui a été précédemment pris
pthread_mutex_destroy : détruit un mutex
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Exemple
#include <pthread.h> <stdlib.h> <string.h>
typedef struct _employee
{
pthread_mutex_t lock;
char *firstname;
char *lastname;
struct _employee *manager;
int idnumber;
} EMPLOYEE;
extern int IDnumber;
extern pthread_mutex_t IDlock;
EMPLOYEE * EmployeeNew (char *first, char *last)
{
EMPLOYEE *ep;
if (!(ep = (EMPLOYEE *) malloc (sizeof (*ep))))
return (NULL);
ep->firstname = strdup (first);
ep->lastname = strdup (last);
pthread_mutex_lock (&IDlock);
ep->idnumber = IDnumber++;
pthread_mutex_unlock (&IDlock);
ep->manager = NULL;
return (ep);
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Variables conditions
●
●
●
Utilisées pour bloquer un thread jusqu'à ce
qu'une condition soit réalisée
Un mutex est associé à cette condition
Il est pris par le thread qui trouve la condition
réalisée
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
#include <pthread.h>
typedef struct _node
{
struct _node *next;
} NODE;
static NODE list;
static pthread_mutex_t list_lk;
static pthread_cond_t list_cv;
static NODE end_message;
Exemple
#define BUFSIZE 512
void * consumer (void *arg)
{
for (;;)
{
NODE *elemp;
pthread_mutex_lock (&list_lk);
while (empty_list ())
pthread_cond_wait (&list_cv, &list_lk);
elemp = (NODE *)dequeue ();
pthread_mutex_unlock (&list_lk);
if (process (elemp) == 0)
break;
}
return (0);
}
void * producer (void *arg)
{
int fd = (int) arg;
int n;
char buf[BUFSIZE];
/* Recoit un message d'un socket */
while ((n = recv (fd, buf, BUFSIZE, 0)) !=
-1)
{
NODE *listp;
if (n == 0)
listp = &end_message;
else if (!(listp = (NODE *)build_list
(buf, n)))
continue;
pthread_mutex_lock (&list_lk);
enqueue (listp);
pthread_cond_signal (&list_cv);
pthread_mutex_unlock (&list_lk);
if (n == 0)
break;
}
close (fd);
return (0);
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS