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