pthreads(7) Miscellaneous Information Manual pthreads(7) NOM pthreads - Threads POSIX DESCRIPTION POSIX.1 decrit une serie d'interfaces (fonctions et fichiers d'en-tetes) pour la programmation multithread, couramment appelee threads POSIX, ou pthreads. Un unique processus peut contenir plusieurs threads, qui executent tous le meme programme. Ces threads partagent la meme memoire globale (segments de donnees et tas), mais chaque thread a sa propre pile (variables automatiques). POSIX.1 requiert aussi que les threads partagent une serie d'autres attributs (ces attributs sont par processus, plutot que par thread) : - identifiant de processus (PID) - identifiant de processus parent (PPID) - identifiant de groupe de processus (PGID) et identifiant de session (SID) - terminal de controle - identifiants d'utilisateur et de groupe - descripteurs de fichier ouverts - verrouillages d'enregistrements (consultez fcntl(2)) - gestion de signaux - masque de creation de mode de fichier (umask(2)) - repertoire de travail (chdir(2)) et repertoire racine (chroot(2)) - temporisations d'intervalle (setitimer(2)) et temporisations POSIX (timer_create(2)) - valeur de politesse (setpriority(2)) - limites de ressources (setrlimit(2)) - mesures de consommation de temps CPU (times(2)) et de ressources (getrusage(2)) En plus de la pile, POSIX.1 indique que plusieurs autres attributs sont distincts pour chaque thread, dont les suivants : - identifiant de thread (le type de donnee pthread_t) - masque de signaux (pthread_sigmask(3)) - la variable errno - pile de signaux specifique (sigaltstack(2)) - politique et priorite d'ordonnancement temps reel (sched(7)) Les caracteristiques specifiques a Linux suivantes sont egalement distinctes pour chaque thread : - capacites (consultez capabilities(7)) - affinite CPU (sched_setaffinity(2)) Valeurs de retour des fonctions pthreads La plupart des fonctions pthreads renvoient 0 en cas de succes et un numero d'erreur en cas d'echec. Les numeros d'erreur pouvant etre renvoyes ont la meme signification que ceux renvoyes dans errno par les appels systeme conventionnels et les fonctions de la bibliotheque C. Notez que les fonctions pthreads ne positionnent pas errno. Pour chacune des fonctions pthreads qui peuvent produire une erreur, POSIX.1-2001 specifie que la fonction ne peut pas echouer avec l'erreur EINTR. Identifiants de thread Chacun des threads d'un processus a un unique identifiant de thread (stocke dans le type pthread_t). Cet identifiant est renvoye a l'appelant de pthread_create(3) et un thread peut obtenir son propre identifiant de thread en utilisant pthread_self(3). Les identifiants de threads ne sont garantis d'etre uniques qu'a l'interieur d'un processus. Dans toutes les fonctions pthreads qui acceptent un identifiant de thread comme argument, par definition, cet identifiant fait reference a un thread dans le meme processus que celui de l'appelant. Le systeme peut reutiliser un identifiant de thread apres qu'un thread qui s'est termine a ete rejoint ou qu'un thread detache se soit termine. POSIX precise : << Si une application essaie d'utiliser un identifiant de thread dont la duree de vie est depassee, le comportement est indefini. >>. Fonctions sures du point de vue des threads Une fonction sure du point de vue des threads est une fonction qui peut etre appelee en toute surete (c'est-a-dire qu'elle renverra le meme resultat d'ou qu'elle soit appelee) par plusieurs threads en meme temps. POSIX.1-2001 et POSIX.1-2008 exigent que toutes les fonctions indiquees dans la norme soient sures du point de vue des threads, exceptees les fonctions suivantes : asctime() basename() catgets() crypt() ctermid() avec un parametre 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() [POSIX.1-2001 uniquement (fonction supprimee dans POSIX.1-2008)] encrypt() endgrent() endpwent() endutxent() fcvt() [POSIX.1-2001 uniquement (fonction supprimee dans POSIX.1-2008)] ftw() gcvt() [POSIX.1-2001 uniquement (fonction supprimee dans POSIX.1-2008)] getc_unlocked() getchar_unlocked() getdate() getenv() getgrent() getgrgid() getgrnam() gethostbyaddr() [POSIX.1-2001 uniquement (fonction supprimee dans POSIX.1-2008)] gethostbyname() [POSIX.1-2001 uniquement (fonction supprimee dans POSIX.1-2008)] 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() strsignal() [Ajoutee dans POSIX.1-2008] strtok() system() [Ajoutee dans POSIX.1-2008] tmpnam() avec un parametre non NULL ttyname() unsetenv() wcrtomb() si son dernier parametre est NULL wcsrtombs() si son dernier parametre est NULL wcstombs() wctomb() Fonctions pour annulations sures asynchrones Une fonction pour annulations sures asynchrones peut etre appelee sans risque dans une application ou l'annulation asynchrone est activee (consultez pthread_setcancelstate(3)). POSIX.1-2001 et POSIX.1-2008 exigent que seules les fonctions suivantes soient pour annulations sures asynchrones : pthread_cancel() pthread_setcancelstate() pthread_setcanceltype() Points d'annulation POSIX.1 specifie que certaines fonctions doivent, et certaines autres fonctions peuvent, etre des points d'annulation. Si un thread est annulable, que son type d'annulation est differe (<< deferred >>) et qu'une demande d'annulation est en cours pour ce thread, alors le thread est annule quand il appelle une fonction qui est un point d'annulation. POSIX.1-2001 et/ou POSIX.1-2008 exigent que les fonctions suivantes soient des points d'annulation : accept() aio_suspend() clock_nanosleep() close() connect() creat() fcntl() F_SETLKW fdatasync() fsync() getmsg() getpmsg() lockf() F_LOCK mq_receive() mq_send() mq_timedreceive() mq_timedsend() msgrcv() msgsnd() msync() nanosleep() open() openat() [Ajoutee dans POSIX.1-2008] pause() poll() pread() pselect() pthread_cond_timedwait() pthread_cond_wait() pthread_join() pthread_testcancel() putmsg() putpmsg() pwrite() read() readv() recv() recvfrom() recvmsg() select() sem_timedwait() sem_wait() send() sendmsg() sendto() sigpause() [POSIX.1-2001 seulement (deplacee dans la liste << may >> dans POSIX.1-2008)] sigsuspend() sigtimedwait() sigwait() sigwaitinfo() sleep() system() tcdrain() usleep() [POSIX.1-2001 seulement(fonction retiree dans POSIX.1-2008)] wait() waitid() waitpid() write() writev() POSIX.1-2001 et/ou POSIX.1-2008 indiquent que les fonctions suivantes peuvent etre des points d'annulation : access() asctime() asctime_r() catclose() catgets() catopen() chmod() [Ajoutee dans POSIX.1-2008] chown() [Ajoutee dans POSIX.1-2008] closedir() closelog() ctermid() ctime() ctime_r() dbm_close() dbm_delete() dbm_fetch() dbm_nextkey() dbm_open() dbm_store() dlclose() dlopen() dprintf() [Ajoutee dans POSIX.1-2008] endgrent() endhostent() endnetent() endprotoent() endpwent() endservent() endutxent() faccessat() [Ajoutee dans POSIX.1-2008] fchmod() [Ajoutee dans POSIX.1-2008] fchmodat() [Ajoutee dans POSIX.1-2008] fchown() [Ajoutee dans POSIX.1-2008] fchownat() [Ajoutee dans POSIX.1-2008] fclose() fcntl() (pour n'importe quelle valeur de l'argument de commande) fflush() fgetc() fgetpos() fgets() fgetwc() fgetws() fmtmsg() fopen() fpathconf() fprintf() fputc() fputs() fputwc() fputws() fread() freopen() fscanf() fseek() fseeko() fsetpos() fstat() fstatat() [Ajoutee dans POSIX.1-2008] ftell() ftello() ftw() futimens() [Ajoutee dans POSIX.1-2008] fwprintf() fwrite() fwscanf() getaddrinfo() getc() getc_unlocked() getchar() getchar_unlocked() getcwd() getdate() getdelim() [Ajoutee dans POSIX.1-2008] getgrent() getgrgid() getgrgid_r() getgrnam() getgrnam_r() gethostbyaddr() [POSIX.1-2001 seulement (fonction retiree dans POSIX.1-2008)] gethostbyname() [POSIX.1-2001 seulement (fonction retiree dans POSIX.1-2008)] gethostent() gethostid() gethostname() getline() [Ajoutee dans POSIX.1-2008] getlogin() getlogin_r() getnameinfo() getnetbyaddr() getnetbyname() getnetent() getopt() (si opterr est different de zero) getprotobyname() getprotobynumber() getprotoent() getpwent() getpwnam() getpwnam_r() getpwuid() getpwuid_r() gets() getservbyname() getservbyport() getservent() getutxent() getutxid() getutxline() getwc() getwchar() getwd() [POSIX.1-2001 seulement (fonction retiree dans POSIX.1-2008)] glob() iconv_close() iconv_open() ioctl() link() linkat() [Ajoutee dans POSIX.1-2008] lio_listio() [Ajoutee dans POSIX.1-2008] localtime() localtime_r() lockf() [Ajoutee dans POSIX.1-2008] lseek() lstat() mkdir() [Ajoutee dans POSIX.1-2008] mkdirat() [Ajoutee dans POSIX.1-2008] mkdtemp() [Ajoutee dans POSIX.1-2008] mkfifo() [Ajoutee dans POSIX.1-2008] mkfifoat() [Ajoutee dans POSIX.1-2008] mknod() [Ajoutee dans POSIX.1-2008] mknodat() [Ajoutee dans POSIX.1-2008] mkstemp() mktime() nftw() opendir() openlog() pathconf() pclose() perror() popen() posix_fadvise() posix_fallocate() posix_madvise() posix_openpt() posix_spawn() posix_spawnp() posix_trace_clear() posix_trace_close() posix_trace_create() posix_trace_create_withlog() posix_trace_eventtypelist_getnext_id() posix_trace_eventtypelist_rewind() posix_trace_flush() posix_trace_get_attr() posix_trace_get_filter() posix_trace_get_status() posix_trace_getnext_event() posix_trace_open() posix_trace_rewind() posix_trace_set_filter() posix_trace_shutdown() posix_trace_timedgetnext_event() posix_typed_mem_open() printf() psiginfo() [Ajoutee dans POSIX.1-2008] psignal() [Ajoutee dans POSIX.1-2008] pthread_rwlock_rdlock() pthread_rwlock_timedrdlock() pthread_rwlock_timedwrlock() pthread_rwlock_wrlock() putc() putc_unlocked() putchar() putchar_unlocked() puts() pututxline() putwc() putwchar() readdir() readdir_r() readlink() [Ajoutee dans POSIX.1-2008] readlinkat() [Ajoutee dans POSIX.1-2008] remove() rename() renameat() [Ajoutee dans POSIX.1-2008] rewind() rewinddir() scandir() [Ajoutee dans POSIX.1-2008] scanf() seekdir() semop() setgrent() sethostent() setnetent() setprotoent() setpwent() setservent() setutxent() sigpause() [Ajoutee dans POSIX.1-2008] stat() strerror() strerror_r() strftime() symlink() symlinkat() [Ajoutee dans POSIX.1-2008] sync() syslog() tmpfile() tmpnam() ttyname() ttyname_r() tzset() ungetc() ungetwc() unlink() unlinkat() [Ajoutee dans POSIX.1-2008] utime() [Ajoutee dans POSIX.1-2008] utimensat() [Ajoutee dans POSIX.1-2008] utimes() [Ajoutee dans POSIX.1-2008] vdprintf() [Ajoutee dans POSIX.1-2008] vfprintf() vfwprintf() vprintf() vwprintf() wcsftime() wordexp() wprintf() wscanf() Une implementation peut egalement indiquer d'autres fonctions non specifiees dans la norme comme etant des points d'annulation. En particulier, une implementation marquera probablement toute fonction non standard qui peut bloquer comme etant un point d'annulation (cela inclut la plupart des fonctions qui peuvent modifier des fichiers). Il est a remarquer que meme si une application n'utilise pas d'annulation asynchrone, l'appel d'une fonction de la liste ci-dessus a partir d'un gestionnaire de signal asynchrone peut provoquer l'equivalent d'une annulation asynchrone. Le code sous-jacent de l'utilisateur peut ne pas s'attendre a une annulation asynchrone et l'etat des donnees de l'utilisateur peut devenir incoherent. Par consequent, les signaux doivent etre utilises avec precaution lors de l'entree dans une region d'annulation differee. Compiler sous Linux Sous Linux, les programmes utilisant l'API pthreads doivent etre compiles avec cc -pthread. Implementations des threads POSIX sous Linux Deux implementations differentes des threads ont ete fournies par la bibliotheque C de GNU sous Linux : LinuxThreads Il s'agit de l'implementation des Pthreads originelle. Depuis la glibc 2.4, cette implementation n'est plus prise en charge. NPTL (Native POSIX Threads Library) Il s'agit de l'implementation moderne des Pthreads. Par rapport a LinuxThreads, NPTL se conforme mieux aux exigences de la norme POSIX.1 et fournit une meilleure performance lors de la creation d'un grand nombre de threads. NPTL est disponible depuis la glibc 2.3.2 et necessite des fonctionnalites presentes dans le noyau Linux 2.6. Ces deux implementation sont dit de type 1:1, ce qui veut dire que chaque thread correspond a une entite d'ordonnancement du noyau. Les deux implementations utilisent l'appel systeme clone(2) de Linux. Dans NPTL, les primitives de synchronisation de threads (mutexes, jonction de thread, etc.) sont implementees avec l'appel systeme futex(2) de Linux. LinuxThreads Les fonctionnalites importantes de cette implementation sont les suivantes : - En plus du thread principal (initial) et des threads crees par le programme avec pthread_create(3), l'implementation cree un thread de gestion. Ce thread s'occupe de la creation et de la terminaison des threads. Des problemes peuvent survenir si ce thread est tue de facon imprevue. - Les signaux sont utilises en interne par l'implementation. Sous Linux 2.2 et suivants, les trois premiers signaux temps reel sont utilises (voir aussi signal(7)). Sous les noyaux plus anciens, LinuxThreads utilise SIGUSR1 et SIGUSR2. Les applications doivent eviter d'utiliser un jeu de signaux utilise par l'implementation. - Les threads ne partagent pas leur identifiant de processus. (En fait, les threads LinuxThreads sont implementes comme des processus partageant plus d'informations qu'a l'habitude, mais pas leur identifiant de processus.) Les threads LinuxThreads (y compris le thread de gestion) sont visibles comme des processus differents avec ps(1). L'implementation LinuxThreads s'ecarte de la specification POSIX.1 par plusieurs aspects, dont les suivants : - Les appels a getpid(2) renvoient une valeur distincte dans chaque thread. - Les appels a getppid(2) dans les threads autres que le thread principal renvoient l'identifiant de processus du thread de gestion ; a la place, getppid(2) dans ces threads renvoie la meme valeur que getppid(2) dans le thread principal. - Lorsqu'un thread cree un nouveau processus enfant avec fork(2), n'importe quel thread doit pouvoir utiliser wait(2) sur l'enfant. Cependant, l'implementation ne permet qu'au thread ayant cree l'enfant d'appeler wait(2) sur lui. - Lorsqu'un thread appelle execve(2), tous les autres threads sont termines (comme le prescrit POSIX.1). Cependant, le processus resultant a le meme PID que le thread ayant appele execve(2) : il doit avoir le meme PID que le thread principal. - Les threads ne partagent pas leurs identifiants d'utilisateur et de groupe. Cela peut causer des complications pour les programmes set-user-ID et provoquer des erreurs dans les fonctions pthreads si une application change d'identifiant avec seteuid(2) et consorts. - Les threads ne partagent pas l'identifiant de session et de groupe de processus. - Les threads ne partagent pas les verrouillages d'enregistrement crees avec fcntl(2). - L'information renvoyee par times(2) et getrusage(2) est par thread au lieu d'etre par processus. - Les threads ne partagent pas les valeurs << undo >> de semaphore (voir semop(2)). - Les threads ne partagent pas les temporisations d'intervalle. - Les threads ne partagent pas leur valeur de politesse. - POSIX.1 distingue les notions de signal envoye au processus dans son ensemble et de signal envoye a un thread individuellement. Selon POSIX.1, un signal envoye au processus (par exemple avec kill(2)) sera gere par un thread choisi arbitrairement au sein du processus. LinuxThreads ne permet pas d'envoyer un signal au processus, mais seulement a un thread specifique. - Les threads ont des parametres de pile de signaux specifique distincts. Cependant, les parametres de pile specifique d'un nouveau thread sont copies a partir du thread qui l'a cree, ce qui veut dire que les threads partagent initialement une meme pile de signaux specifique. (Un nouveau thread devrait demarrer sans pile de signaux specifique. Si deux threads gerent un signal sur leur pile specifique au meme moment, des echecs imprevisibles du programme risquent de se produire.) NPTL Avec NPTL, tous les threads d'un processus sont places dans le meme groupe de threads. Tous les membres d'un groupe de threads partagent le meme PID. NPTL n'utilise pas de thread de gestion. NPTL utilise en interne les deux premiers signaux temps reel. Ces signaux ne peuvent pas etre utilises dans les applications. Consulter nptl(7) pour davantage de details. NPTL a encore au moins une non conformite a POSIX.1 : - Les threads ne partagent pas leur valeur de politesse. Certaines non conformites n'apparaissent qu'avec des noyaux plus anciens : - l'information renvoyee par times(2) et getrusage(2) est par thread au lieu d'etre globale au processus (corrige dans Linux 2.6.9) ; - les threads ne partagent pas les limites de ressources (corrige dans Linux 2.6.10) ; - les threads ne partagent pas les temporisations d'intervalle (corrige dans Linux 2.6.12) ; - seul le thread principal est autorise a demarrer une nouvelle session avec setsid(2) (corrige dans le noyau 2.6.16) ; - seul le thread principal est autorise a rendre le processus leader de son groupe de processus avec setpgid(2) (corrige dans le noyau 2.6.16) ; - Les threads ont des parametres de pile de signaux specifique distincts. Cependant, les parametres de pile de signaux specifique d'un nouveau thread sont copies de ceux du thread qui l'a cree, de facon que les threads partagent initialement une pile de signaux specifique dans Linux 2.6.16). Veuillez noter les points suivants a propos de l'implementation NPTL : - Si la limite souple de taille de pile (voir dans setrlimit(2) la description de RLIMIT_STACK) est differente de unlimited, cette valeur determine la taille de pile par defaut pour les nouveaux threads. Pour avoir un effet, cette limite doit etre definie avant le demarrage du programme, par exemple en utilisant la commande ulimit -s de l'interpreteur de commandes (limit stacksize dans csh). Determiner l'implementation des threads utilisee Depuis glibc 2.3.2, la commande getconf(1) peut etre utilisee pour determiner l'implementation de threads du systeme, par exemple : bash$ getconf GNU_LIBPTHREAD_VERSION NPTL 2.3.4 Avec des versions plus anciennes de la glibc, une commande comme la suivante devrait etre suffisante pour determiner l'implementation de threads par defaut : bash$ $( ldd /bin/ls | grep libc.so | awk '{print $3}' ) | \ egrep -i 'threads|nptl' Native POSIX Threads Library by Ulrich Drepper et al Choisir l'implementation des threads : LD_ASSUME_KERNEL Sur les systemes avec une glibc fournissant a la fois LinuxThreads et NPTL (i.e. glibc 2.3.x), la variable d'environnement LD_ASSUME_KERNEL peut etre utilisee pour ecraser le choix par defaut d'implementation de threads fait par l'editeur de liens dynamiques. Cette variable indique a l'editeur de liens dynamiques qu'il doit faire comme s'il etait execute avec une version particuliere du noyau. En indiquant une version du noyau ne fournissant pas les fonctionnalites necessitees par NPTL, on peut forcer l'utilisation de LinuxThreads. (La raison la plus probable pour cela est d'executer une application (boguee) qui depend d'un comportement de LinuxThreads non conforme a la specification.) Par exemple : bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \ awk '{print $3}' ) | egrep -i 'threads|nptl' linuxthreads-0.10 by Xavier Leroy VOIR AUSSI clone(2), fork(2), futex(2), gettid(2), proc(5), attributes(7), futex(7), nptl(7), sigevent(3type), signal(7) Diverses pages de manuel de Pthreads, par exemple : pthread_atfork(3), pthread_attr_init(3), pthread_cancel(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_mutexattr_destroy(3), pthread_mutexattr_init(3), pthread_once(3), pthread_spin_init(3), pthread_spin_lock(3), pthread_rwlockattr_setkind_np(3), pthread_setcancelstate(3), pthread_setcanceltype(3), pthread_setspecific(3), pthread_sigmask(3), pthread_sigqueue(3) et pthread_testcancel(3) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Frederic Hantrais et Jean- Paul Guillonneau Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 31 octobre 2023 pthreads(7)