40
Threads Posix.1c/1003b Threads Posix.1c/1003b IEEE IEEE Présentation Création

Threads Posix.1c/1003b IEEE IEEE Présentation Création

Embed Size (px)

Citation preview

Page 1: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Threads Posix.1c/1003bThreads Posix.1c/1003bIEEEIEEE

Présentation

Création

Page 2: Threads Posix.1c/1003b IEEE IEEE Présentation Création

PrésentationPrésentation

Un thread est un déroulement d'un programme qui s'exécute parallèlement à d'autres unités en cours d'exécution.

Les différents threads d'une application partagent un même espace d'adressage. L'accès concurrentiel aux mêmes données nécessite une synchronisation pour éviter les interférences.

En outre chaque thread dispose d'une pile et d'un contexte d'exécution contenant les registres du processeur et un compteur d'instruction.

L'idée générale est de détacher le flot d'exécution des ressources

Page 3: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Le contexte processusLe contexte processus

Contexte d'exécution•Registres généraux •Registres d'état•SP•PC

Contexte du noyau•Tables fichiers •Structure MV•Segment données

Pile

Tas

Données

code

Code données et pileContexte du processus

Page 4: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Le contexte processus : Détacher le flot des ressourcesLe contexte processus : Détacher le flot des ressources

Contexte du thread•Registres généraux •Registres d'état•SP•PC

Contexte du noyau•Tables fichiers •Structure MV•Segment données

Pile

Tas

Données

code

Code et données

Thread

Page 5: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Processus multi-threadProcessus multi-thread

Contexte du noyau•Tables fichiers •Structure MV•Segment données

Tas

Données

code

Code et données

Contexte du thread•Registres généraux •Registres d'état•SP2•PC2

Pile2

Thread 2

Contexte du thread•Registres généraux •Registres d'état•SP1•PC1

Pile1

Thread 1

Page 6: Threads Posix.1c/1003b IEEE IEEE Présentation Création

La bibliothèque des threadsLa bibliothèque des threads

http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/pthread_create.3.html

Page 7: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Le manLe manNompthread_create - créé un nouveau thread Synopsis#include <pthread.h> int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg); Descriptionpthread_create créé un nouveau thread s'éxécutant concurremment avec le thread appelant. Le nouveau thread exécute la fonction start_routine en lui passant arg comme premier argument. Le nouveau thread s'achève soit explicitement en appelant pthread_exit(3) , ou implicitement lorsque la fonction start_routine s'achève. Ce dernier cas est équivalent à appelér pthread_exit(3) avec la valeur renvoyée par start_routine comme code de sortie. L'argument attr indique les attributs du nouveau thread. Voir pthread_attr_init(3) pour une liste complète des attributs. L'argument attr peut être NULL, auquel cas, les attributs par défaut sont utilisés: le thread créé est joignable (non détaché) et utilise la politique d'ordonnancement usuelle (pas temps-réél). Valeur RenvoyéeEn cas de succès, l'identifiant du nouveau thread est stocké à l'emplacement mémoire pointé par l'argument thread, et 0 est renvoyé. En cas d'erreur, un code d'errur non nul est renvoyé. ErreursEAGAIN

pas assez de ressources système pour créer un processus pour le nouveau thread.

EAGAIN il y a déjà plus de PTHREAD_THREADS_MAX threads actifs.

AuteurXavier Leroy <[email protected]> TraductionThierry Vignaud <[email protected]>, 2000 Voir Aussipthread_exit(3) , pthread_join(3) , pthread_detach(3) , pthread_attr_init(3) .

Page 8: Threads Posix.1c/1003b IEEE IEEE Présentation Création

pthread.hpthread.h

ftp://sources.redhat.com/pub/pthreads-win32/dll-latest/include/

lien

Page 9: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Création d'un threadCréation d'un thread

Un type opaque est utilisé pour distinguer les threads d'une application

unsigned long pthread_t (dans la bibliothèque LinuxThreads)

Création d'un thread

int pthread_create(

1. pthread_t * pThread,

2. const pthread_attr_t * attr,

3. void* (*pFunction) (void*),

4. void * pArg

);

Cette routine renvoie 0 si elle a réussi, sinon elle renvoie un numéro de lerreur survenue.

pthread_create ne remplit pas la var errno.

Page 10: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Le code C de thread_createLe code C de thread_create

/* Thread creation */

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg){ pthread_descr self = thread_self(); struct pthread_request request; if (__pthread_manager_request < 0) { if (pthread_initialize_manager() < 0) return EAGAIN; } request.req_thread = self; request.req_kind = REQ_CREATE; request.req_args.create.attr = attr; request.req_args.create.fn = start_routine; request.req_args.create.arg = arg; sigprocmask(SIG_SETMASK, (const sigset_t *) NULL, &request.req_args.create.mask); __libc_write(__pthread_manager_request, (char *) &request, sizeof(request)); suspend(self); if (self->p_retcode == 0) *thread = (pthread_t) self->p_retval; return self->p_retcode;}

Page 11: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Arguments Arguments

1. Le premier argument pthread_t * pThread, est un pointeur qui sera réalisé par la routine avec l'identifiant du nouveau thread.

2. le second argument const pthread_attr_t * attr, correspond aux attributs dont on desire doter le nouveau thread. Par défaut, le thread reçoit des attributs standard.

3. Le troisième argument void* (*pFunction) (void*), est un pointeur représentant la fonction principale du nouveau thread (c'est ce qu'il doit faire). Dès la création du thread, la fonction est invoquée en recevant comme argument le pointeur passé en dernière position. Le prototype de cette fonction est imposé et ne peut donc pas être modifié.

4. Le quatrième argument void * pArg est de type void *, il sera ainsi transformé dans le type de l'argument que l'on veur passer au thread. Cet argument est généralement un numéro permettant d'indiquer le travail à réaliser.

Page 12: Threads Posix.1c/1003b IEEE IEEE Présentation Création

TerminaisonTerminaison

La terminaison a lieu lorsque

1. La fonction principale se termine.

2. Par l'appel de la fonction pthread_exit

le thread est alors éliminé

par l'appel de pthread_exit toutes les fonctions de nettoyage sont invoquées

Page 13: Threads Posix.1c/1003b IEEE IEEE Présentation Création

TerminaisonTerminaison

Prototype de la fonction

void pthread_exit(void * pReturnValue);

Page 14: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Récupération d'une valeur de retourRécupération d'une valeur de retour

Pour avoir la valeur de retour d'un thread terminé on utilise

int pthread_join(

1. pthread_t thread,

2. void ** pPtrReturnValue

);

La fonction peut échouer si le thread attendu n'existe pas ; s'il est détaché ou si le thread demande sa propre fin

Page 15: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Les argument de pthread_joinLes argument de pthread_join

L'argument pthread_t thread, est le thread qui se termine

Le deuxième argument void ** pPtrReturnValue est un pointeur sur un void * utilisé pour recevoir la valeur de retour du thread. Cette valeur de retour est spécifiée a la fin du thread grâce a la fonction pthread_exit. Ce dernier argument peut être NULL si nous ne sommes pas intéressé par la valeur de retour du thread.

Page 16: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Récupération d'un entier comme code de retourRécupération d'un entier comme code de retour

Pour conserver la portabilité d'un programme, la procédure a lieu en deux étapes

1. dans fonctionthread

int i=valretour;

pthread_exit((void*)i);

2. dans le main par exemple

void * retour;

pthread_join(threadid, & retour);

Ainsi, il faut utiliser d'abord un pointeur void * temporaire, qu'on transforme ensuite en int.

Page 17: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Interaction avec le thread principalInteraction avec le thread principal

Thread Principal

Fin pthread_create()Fin pthread_create()

pthread_join()pthread_join()

fin pthread_join()fin pthread_join()

exit()exit()

thread

ptread_exit()

pthread_create()pthread_create()

Page 18: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Synchronisation et communication de tâchesSynchronisation et communication de tâches

Dans POSIX, les outils sont plus rapides et plus puissants que les IPC

Sémaphore binaire

Les mutex sont dédiés à l'exclusion mutuelle.

Les attributs des mutex permettent de choisir le protocole de gestion de ressource associé

Sémaphores en lecture/écriture

POSIX.1c propose les sémaphore en lecture/écriture

Aucun protocole de gestion de ressources

Variable conditionnelle

Utilisée avec un mutex pour créer des moniteurs

On peut utiliser une attente bornée qui ne sera jamais signalée.

RDV

Après la création d'un RDV synchronisé des tâches peuvent s'attendre mutuellement

Page 19: Threads Posix.1c/1003b IEEE IEEE Présentation Création

zones d'exclusions mutuelleszones d'exclusions mutuelles

La synchronisation est un des enjeux essentiels du développement d'application multithreads entre les différents fils d'exécution concurrents.

Pour accéder à des données communes, il est indispensable de mettre en œuvre un mécanisme d'exclusion mutuelle des threads.

Cas des mutex

Pour créer un mutex, la librairie POSIX fournie la fonction suivante :

int pthread_mutex_init(

1. pthread_mutex_t * pMutex,

2. pthread_mutexattr_t * pAttributs

);

Pour détruire un mutex, nous utilisons la fonction suivante :

int pthread_mutex_destroy(pthread_mutex_t * pMutex);

Page 20: Threads Posix.1c/1003b IEEE IEEE Présentation Création

ParamètresParamètres

Le premier paramètre est un pointeur sur un pthread_mutex_t destiné a recevoir le descripteur du mutex nouvellement créé.

Le second paramètre pAttributs est utilisé pour paramétrer le mutex, cette variable regroupe tous les attributs du mutex, les paramètres par défaut sont obtenus avec un pointeur Null.

Page 21: Threads Posix.1c/1003b IEEE IEEE Présentation Création

EmploiEmploi

La fonction pthread_mutex_init est employée comme ceci

pthread_mutex mutex

pthread_mutexattr_t muxeattr

/*initialisationdemutexattr*/

/*initialisationdumutex*/

if ((mutex=malloc (sizeof(pthread_mutex_t))==Null)

return (-1);

pthread_mutex_init(&mutex,&mutexattr);

Page 22: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Fonction de verrouillage et déverrouillageFonction de verrouillage et déverrouillage

Si le mutex est libre, il peut être immédiatement verrouillé et attribué au thread appelant. Si le mutex est déjà maintenu par un autre thread, la fonction reste bloquée (indéfiniment). Ce n'est pas un point d'annulation.

int pthread_mutex_lock(pthread_mutex_t * pMutex);

Dès que le thread a fini de travailler avec les données protégées, le mutex doit être déverrouillé pour laisser la place a d’autres thread.Ceci est simplement réalisé en appelant la fonction suivante :

int pthread_mutex_unlock(pthread_mutex_t * pMutex);

Page 23: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Attente conditionelleAttente conditionelle

Lorsqu'un processus attend qu'un événement survienne on emploie une technique de synchronisation a base de variable conditionnelle.Un thread attend une condition ; il est avertit par un autre thread lorsqu'elle est réalisée.

Lorsqu’un variable de condition n’est plus utilisée, il faut la libérée avec la fonction suivante :int pthread_cond_destroy(pthread_cond_t * pCond);

Page 24: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Attente conditionelleAttente conditionelle

Le principe repose sur deux fonctions de manipulation des conditionsint pthread_cond_wait(

pthread_cond_t * pCond,pthread_mutex_t * pMutex);

int pthread_cond_signal(pthread_cond_t * pCond);

Sans oublierint pthread_cond_init(

pthread_cond_t * pCond, pthread_condattr_t * pCandAttr);

Page 25: Threads Posix.1c/1003b IEEE IEEE Présentation Création

ScénarioScénario

Toutes les variables de condition ont besoin d’être associé à un mutex spécifique qui va bloquer le thread jusqu'à l’émission de la notification.

Thread attendant la condition Thread signalant la condition

pthread_mutex_lock

pthread_cond_wait

déblocage du mutex

wait

pthread_mutex_lock

pthread_cond_signal

Réveil du thread

pthread_cond_wait

Tentative de récupérer le mutex

pthread_mutex_unlock

Fin de pthread_cond_wait

pthread_mutex_unlock

Page 26: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Fonction d'attente temporiséeFonction d'attente temporisée

Il faut préciser l'heure maximale et non la durée

int pthread_cond_timewait(

1. pthread_cond_t * pCond,

2. pthread_mutex_t * pMutex,

3. struct timespec * expiration

);

pthread_cond_wait a le comportement d'un point d'annulation. Lorsqu'un thread reçoit une demande d'annulation durant cette fonction d'attente, elle se termine mais doit récupérer avant le mutex associé à la condition. Cela signifie qu'elle peut bloquer indéfiniment avant de se terminer.

Page 27: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Annulation d'un threadAnnulation d'un thread

L'annulation doit thread doit laisser les données dans un état prévisible, et le seul état prévisible du mutex associé à un appel pthread_cond_wait() est le verrouillage. Bien sur, le thread ne doit pas laisser le mutex bloqué. On utilise une fonction de nettoyage.

Page 28: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Fonction de nettoyageFonction de nettoyage

Lorsqu'un thread s'attribue une ressource qui nécessite une libération ultérieure, il enregistre le nom de la routine de libération dans une pile spéciale. Lorsque le thread se termine, les routines sont dépilées et exécutées

void pthread_cleanup_push(

1. void(*fonction)(void * argument),

2. void * argument

);

void pthread_cleanup_pop(int execution_routine);

Page 29: Threads Posix.1c/1003b IEEE IEEE Présentation Création

OrdonnancementOrdonnancement

Deux niveaux de programmation concurrente sont offert dans Posix

les processus et les threads

L'ordonnancement peut se faire à deux niveaux

local et global

Page 30: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Ordonnancement localOrdonnancement local

1

2

n

P1 P4 P12

Pi

Ti Tj

Le modèle d'ordonnancement est hiérarchiqueLes processus sont en concurrence par prioritéLe temps alloué à P4 est réparti aux taches

Page 31: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Ordonnancement globalOrdonnancement global

1

2

n

P1 P4 P12

Pi

Ti TjT1

T2

Les taches ou les processus sont ordonnancéesau même niveau

Page 32: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Ordonnancement MixteOrdonnancement Mixte

1

2

n

P1 P4 P12

Pi

Ti TjT1

T2

Page 33: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Avantages/inconvénientsAvantages/inconvénients

Dans un ordonnancement local si une tâche fait une action bloquante le processus est bloqué.

Les tâches d'un même processus ne peuvent être ordonnancées sur un multiprocesseurs

Pour modifier dans un ordonnancement global un paramètre influençant l'ordonnancement il faut faire un appel système plus lourd qu'un appel de fonction interne au processus.

Les tâches d'un même processeurs peuvent être ordonnancées sur plusieurs processeurs

Page 34: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Politique d'ordonnancementPolitique d'ordonnancement

SCHED_FIFO

La tâche prête (processus) qui a la plus forte priorité au niveau global et qui est arrivée la première

SCHED_RR

fonctionne comme SCHED_FIFO avec un quantum de temps appliqué par tourniquet

SCHED_OTHER

défini par l'implémentation

SCHED_SPORADIC

La politique de base est la politique SCHED_FIFO, avec une quantité de temps alloué à un serveur dont la capacité est cette quantité

Page 35: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Les attributs d'une tâcheLes attributs d'une tâche

Les attributs d'une tâches peuvent définir

Le type d'ordonnancement à appliquer

La taille de la pile

Une priorité

La définition d'un serveur sporadique associé à la tâche

L'état attaché ou détaché de la tâche

Après la création d'un tâche, il est possible de modifier les attributs d'une tâche.

Page 36: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Les attributs de threadLes attributs de thread

Création et destruction :

int pthread_attr_init ( pthread_attr_t * )

int pthread_attr_destroy (pthread_attr_t * )

Lecture :

int pthread_attr_getXXX (const pthread_attr_t *, T*)

Mise à jour :

int pthread_attr_setXXX ( pthread_attr_t *, T )

XXX représente le nom de l'attribut.

Page 37: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Signification et valeur de XXXSignification et valeur de XXX

detachstate : spécifie s’il sera possible de se synchroniser sur le fil d’exécution une fois qu’il sera terminé.

PTHREAD_CREATE_JOINABLE pour autoriser la synchronisation PTHREAD_CREATE_DETACHED pour la décliner.

schedpolicy correspond à la politique d’ordonnancement employée par le thread.

SCHED_OTHER pour l’ordonnancement classiqueSCHED_RR pour un séquencement temps-réel avec l’algorithme Round RobinSCHED_FIFO pour un ordonnancement temps-réel FIFO.

Inheritsched signale si le thread a sa propre configuration d'ordonnancementPTHREAD_EXPLICIT_SCHED ordonnancement spécifique au threadPTHREAD_INHERIT_SCHED ordonnancement hérité

Page 38: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Liste complèteListe complète

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);

int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);

int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);

int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit);

int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit);

int pthread_attr_setscope(pthread_attr_t *attr, int scope); int pthread_attr_getscope(const pthread_attr_t *attr, int

*scope);

Page 39: Threads Posix.1c/1003b IEEE IEEE Présentation Création

Norme POSIX.1003.bNorme POSIX.1003.b

Page 40: Threads Posix.1c/1003b IEEE IEEE Présentation Création

liensliens

http://old.devpaks.org/show.php?devpak=18

http://sources.redhat.com/pthreads-win32/

http://www.humanfactor.com/pthreads/

http://www.llnl.gov/computing/tutorials/pthreads/