PTHREADS
Section : Manuel du programmeur Linux (
7)
Mise à jour de la version anglaise : 29 mai 2008
Index
Menu principal
NOM
pthreads - Threads POSIX
DESCRIPTION
POSIX.1 spécifie un ensemble d'interfaces (fonctions, fichiers d'entête)
pour la programmation par thread, plus connu sous le nom de threads POSIX
ou Pthreads.
Un seul processus peut contenir plusieurs threads, chacun d'eux exécutant
le même programme.
Ces threads partagent la même mémoire globale
(segments de données et de tas)
mais chaque thread possède sa propre pile (variables automatiques).
POSIX.1 réclame également que les threads partagent un ensemble d'autres
attributs (c'est-à-dire que ces attributs sont à l'échelle du processus
plutôt que spécifiques à chaque thread) :
- -
-
ID du processus (PID)
- -
-
ID du processus parent (PPID)
- -
-
ID du groupe du processus (PGID) et ID de session
- -
-
terminal de contrôle
- -
-
ID utilisateur (UID) et ID de groupe (GID)
- -
-
descripteurs de fichier ouverts
- -
-
verrous d'enregistrement (voir
fcntl(2))
- -
-
dispositions de signaux
- -
-
masque de création de fichier
(umask(2))
- -
-
répertoire courant
(chdir(2))
et répertoire racine
(chroot(2))
- -
-
temporisateurs d'intervalle
(setitimer(2))
et temporisateurs POSIX
(timer_create(3))
- -
-
valeur de « courtoisie »
(setpriority(2))
- -
-
limites des ressources
(setrlimit(2))
- -
-
mesures de la consommation de temps CPU
(times(2))
et de ressources
(getrusage(2))
En plus de la pile, POSIX.1 spécifie divers autres attributs propres à
chaque thread, incluant :
- -
-
ID de thread (TID) (le type de donnée
pthread_t)
- -
-
masque de signaux
(pthread_sigmask(3))
- -
-
la variable
errno
- -
-
pile de signal alternative
(sigaltstack(2))
- -
-
politique et priorité d'ordonnacement temps réel
(sched_setscheduler(2)
et
sched_setparam(2))
Les fonctionnalités suivantes, spécifiques à Linux,
sont également par thread :
- -
-
capacités (voir
capabilities(7))
- -
-
affinité CPU
(sched_setaffinity(2))
Fonctions sûres du point de vue des threads
Une fonction sûre du point de vue des threads est une fonction qui peut
être appelée en toute sureté (c'est-à-dire qu'elle renverra le même
résultat d'où qu'elle soit appelée) par plusieurs threads en même temps.
POSIX.1-2001 réclame que toutes les fonctions indiquées dans la norme
soit sûres du point de vue des threads, excepté les fonctions suivantes :
asctime()
basename()
catgets()
crypt()
ctermid() s'il lui est passé un argument non-NULL
ctime()
dbm_clearerr()
dbm_close()
dbm_delete()
dbm_error()
dbm_fetch()
dbm_firstkey()
dbm_nextkey()
dbm_open()
dbm_store()
dirname()
dlerror()
drand48()
ecvt()
encrypt()
endgrent()
endpwent()
endutxent()
fcvt()
ftw()
gcvt()
getc_unlocked()
getchar_unlocked()
getdate()
getenv()
getgrent()
getgrgid()
getgrnam()
gethostbyaddr()
gethostbyname()
gethostent()
getlogin()
getnetbyaddr()
getnetbyname()
getnetent()
getopt()
getprotobyname()
getprotobynumber()
getprotoent()
getpwent()
getpwnam()
getpwuid()
getservbyname()
getservbyport()
getservent()
getutxent()
getutxid()
getutxline()
gmtime()
hcreate()
hdestroy()
hsearch()
inet_ntoa()
l64a()
lgamma()
lgammaf()
lgammal()
localeconv()
localtime()
lrand48()
mrand48()
nftw()
nl_langinfo()
ptsname()
putc_unlocked()
putchar_unlocked()
putenv()
pututxline()
rand()
readdir()
setenv()
setgrent()
setkey()
setpwent()
setutxent()
strerror()
strtok()
tmpnam() s'il lui est passé un argument non-NULL
ttyname()
unsetenv()
wcrtomb() si son dernier argument est NULL
wcsrtombs() si son dernier argument est NULL
wcstombs()
wctomb()
Compilation sous Linux
Sous Linux, les programmes qui utilisent l'API Pthreads devraient être
compilés en utilisant la commande
cc -pthread.
Implémentations Linux des threads POSIX
Sous Linux, deux implémentations de threading
sont fournies par la glibc :
- LinuxThreads
-
Il s'agit de l'implémentation Pthreads originale.
Depuis la glibc 2.4, cette implémentation n'est plus prise en charge.
- NPTL (Native POSIX Threads Library)
-
Il s'agit de l'implémentation Pthreads moderne.
En comparaison avec LinuxThreads, NPTL fournit une conformité plus proche
des spécifications POSIX.1 et une meilleure performance lorsque l'on crée
un grand nombre de threads.
NPTL est disponible depuis la glibc 2.3.2 et nécessite
des fonctionnalités qui sont présentes dans le noyau Linux 2.6.
Toutes les deux sont appelées implémentations 1:1, signifiant que chaque
thread correspond à une entité d'ordonnacement noyau.
Les deux implémentations utilisent l'appel système Linux
clone(2).
Dans la bibliothèque NPTL, les primitives de synchronisation de thread
(mutexes, attachement de thread, etc.) sont implémentées en utilisant
l'appel système Linux
futex(2).
LinuxThreads
Les fonctionnalités notables de cette implémentation sont les suivantes :
- -
-
En plus du thread principal (initial) et des threads
que le programme crée avec
pthread_create(3),
l'implémentation crée un thread « gestionnaire ».
Ce thread gère la création et la terminaison des threads.
(Des problèmes peuvent survenir si ce thread est tué par inadvertance.)
- -
-
Les signaux sont utilisés de manière interne par l'implémentation.
Sous Linux 2.2 et suivants, les trois premiers signaux temps réel sont
utilisés.
Sur les noyaux plus anciens,
SIGUSR1
et
SIGUSR2
sont utilisés.
Les applications doivent éviter d'utiliser les signaux qui le sont par
l'implémentation.
- -
-
Les threads ne partagent pas les PID.
(En effet, les threads LinuxThreads sont implémentés comme des processus
qui partagent plus d'informations qu'à l'habitude,
mais qui ne partagent pas un PID commun.)
Les threads LinuxThreads (y compris le thread gestionnaire) sont visibles
en tant que processus séparés lorsqu'on utilise
ps(1).
L'implémentation LinuxThreads dévie des spécifications POSIX.1
de plusieurs façons, incluant :
- -
-
Les appels à
getpid(2)
renvoient une valeur différente dans chaque thread.
- -
-
Les appels à
getppid(2)
dans les threads autres que le thread principal renvoient
le PID du thread gestionnaire ; à la place,
getppid(2)
dans ces threads devrait retourner la même valeur que
getppid(2)
dans le thread principal.
- -
-
Lorsqu'un thread crée un nouveau processus fils avec
fork(2),
chaque thread devrait être capable d'attendre
(wait(2))
le fils.
Toutefois, l'implémentation ne permet qu'au thread
qui a créé le fils de l'attendre.
- -
-
Lorsqu'un thread appelle
execve(2),
tous les autres threads sont terminés (comme requis par POSIX.1).
Toutefois, le processus résultant a le même PID que le thread qui a appelé
execve(2) :
il devrait avoir le même PID que le thread principal.
- -
-
Les threads ne partagent pas les UID et GID.
Cela peut provoquer des complications avec les programmes Set-UID
et provoquer des échecs dans les fonctions Pthreads si une application
modifie ses références avec
seteuid(2)
ou une fonction similaire.
- -
-
Les threads ne partagent pas un PGID et un ID de session commun.
- -
-
Les threads ne partagent pas les verrous d'enregistrement créés avec
fcntl(2).
- -
-
Les informations renvoyées par
times(2)
et
getrusage(2)
sont par thread et non à l'échelle du processus.
- -
-
Les threads ne partagent pas les valeurs « undo » des sémaphores (voir
semop(2)).
- -
-
Les threads ne partagent pas les temporisateurs d'intervalles.
- -
-
Les threads ne partagent pas une valeur de « courtoisie » commune.
- -
-
POSIX.1 distingue les notions de signaux qui s'adressent au processus
dans son ensemble et des signaux qui s'adressent aux threads
de manière individuelle.
Suivant POSIX.1, un signal s'adressant à un processus (envoyé par
kill(2),
par exemple) devrait être géré par un seul thread,
choisi arbitrairement dans le processus.
LinuxThreads ne supporte pas la notion de signaux
s'adressant à un processus :
les signaux peuvent seulement être envoyés à des threads spécifiques.
- -
-
Tous les threads ont des configurations distinctes pour les piles
utilisées spécifiquement lors du traitement des signaux.
Toutefois, la configuration d'un thread nouvellement créé est copiée
sur la configuration de son créateur,
aussi partagent-ils la même pile spécifique pour les signaux.
(Il serait préférable qu'un nouveau thread démarre sans pile de traitement
de signaux, car si deux threads gèrent des signaux en utilisant
la même pile, on assistera probablement à des plantages imprévisibles.)
NPTL
Avec NPTL, tous les threads d'un processus sont placés
dans le même groupe de threads ;
tous les membres d'un groupe de threads partagent le même PID.
NPTL n'utilise pas de thread gestionnaire.
NPTL utilise de manière interne les deux premiers signaux temps réel ;
ces signaux ne doivent donc pas être utilisés dans l'application.
NPTL a aussi au moins une non-conformité avec POSIX.1 :
- -
-
Les threads ne partagent pas une valeur de courtoisie commune.
Certaines non-conformités NPTL peuvent apparaîtrent sur d'anciens noyaux :
- -
-
Les informations renvoyées par
times(2)
et
getrusage(2)
sont spécifiques aux threads plutôt que d'être à l'échelle du système
(corrigé dans le noyau 2.6.9).
- -
-
Les threads ne partagent pas les limites de ressources
(corrigé dans le noyau 2.6.10).
- -
-
Les threads ne partagent pas les temporisateurs d'intervalles
(corrigé dans le noyau 2.6.12).
- -
-
Seul le thread principal a le droit de démarrer une nouvelle session avec
setsid(2)
(corrigé dans le noyau 2.6.16).
- -
-
Seul le thread principal a le droit de faire d'un processus un leader
dans un groupe de processus avec
setpgid(2)
(corrigé dans le noyau 2.6.16).
- -
-
Tous les threads ont des configurations distinctes pour les piles utilisées
spécifiquement lors du traitement des signaux.
Toutefois, la configuration d'un thread nouvellement créé est copiée
sur la configuration de son créateur,
aussi partagent-ils la même pile spécifique pour les signaux
(corrigé dans le noyau 2.6.16).
Veuillez noter les points suivants concernant l'implémentation NPTL :
- -
-
Si la limite de ressource souple de taille de pile
(voir la description de
RLIMIT_STACK
dans
setrlimit(2))
est définie à une valeur autre que
unlimited,
cette valeur définit la taille par défaut de la pile
pour les nouveaux threads.
Pour être effective, cette limite doit être définie avant que le programme
ne soit exécuté, peut-être en utilisant la commande shell intégrée
ulimit -s
(limit stacksize
dans le shell C).
Déterminer l'implémentation de threading
Depuis la glibc 2.3.2, la commande
getconf(1)
permet de déterminer l'implémentation de threading du système,
par exemple :
bash$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.3.4
Pour les versions plus anciennes de la glibc,
une commande telle la suivante devrait être suffisante pour déterminer
l'implémentation de threading :
bash$ $( ldd /bin/ls | grep libc.so | awk aq{print $3}aq ) | \
egrep -i aqthreads|nptlaq
Native POSIX Threads Library by Ulrich Drepper et al
Sélectionner l'implémentation de threading : LD_ASSUME_KERNEL
Sur les systèmes dont la glibc supportent LinuxThreads et NPTL
(c'est-à-dire la glibc 2.3.
x),
la variable d'environnement
LD_ASSUME_KERNEL
peut être utilisée pour surcharger le choix par défaut de l'implémention de
threading par l'éditeur de liens dynamique.
Cette variable indique à l'éditeur de liens dynamique de supposer
que l'on utilise une version particulière du noyau.
En spécifiant une version qui ne fournit pas le support nécessaire à NPTL,
on force l'utilisation de LinuxThreads.
(La principale raison pour faire cela est de lancer une application
qui dépend de certains comportements non conformes de LinuxThreads.)
Par exemple :
bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \
awk '{print $3}' ) | egrep -i 'threads|ntpl'
linuxthreads-0.10 by Xavier Leroy
VOIR AUSSI
clone(2),
futex(2),
gettid(2),
futex(7),
et diverses pages de manuel Pthreads, par exemple :
pthread_atfork(3),
pthread_cleanup_push(3),
pthread_cond_signal(3),
pthread_cond_wait(3),
pthread_create(3),
pthread_detach(3),
pthread_equal(3),
pthread_exit(3),
pthread_key_create(3),
pthread_kill(3),
pthread_mutex_lock(3),
pthread_mutex_unlock(3),
pthread_once(3),
pthread_setcancelstate(3),
pthread_setcanceltype(3),
pthread_setspecific(3),
pthread_sigmask(3),
et
pthread_testcancel(3).
TRADUCTION
Ce document est une traduction réalisée par Alain Portal
<aportal AT univ-montp2 DOT fr> le 27 juin 2006
et révisée le 17 juillet 2008.
L'équipe de traduction a fait le maximum pour réaliser une adaptation
française de qualité. La version anglaise la plus à jour de ce document est
toujours consultable via la commande : « LANG=C man 7 pthreads ».
N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute
erreur dans cette page de manuel.
Index
- NOM
-
- DESCRIPTION
-
- Fonctions sûres du point de vue des threads
-
- Compilation sous Linux
-
- Implémentations Linux des threads POSIX
-
- LinuxThreads
-
- NPTL
-
- Déterminer l'implémentation de threading
-
- Sélectionner l'implémentation de threading : LD_ASSUME_KERNEL
-
- VOIR AUSSI
-
- TRADUCTION
-
Dernière mise à jour : 17 juillet 2008