pthread_create
Table des matières
Retour à l'index
NOM
pthread_create – Créer un nouveau thread
BIBLIOTHÈQUE
Bibliothèque de threads POSIX (libpthread, -lpthread)
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void *),
void *restrict arg);
DESCRIPTION
La fonction pthread_create() démarre un nouveau thread (processus léger)
dans le processus appelant. Le nouveau thread commence par appeler
start_routine() ; arg est passé comme unique argument de
start_routine().
Le nouveau thread se termine d'une des manières suivantes :
- -
-
Il appelle pthread_exit(3), en indiquant une valeur de sortie qui sera
disponible pour un autre thread du même processus qui appelle
pthread_join(3).
- -
-
Il sort de la routine start_routine(). C'est équivalent à appeler
pthread_exit(3) avec la valeur fournie à l'instruction return.
- -
-
Il est annulé (voir pthread_cancel(3)).
- -
-
Un des threads du processus appelle exit(3) ou le thread principal sort
de la routine main() ce qui entraîne l'arrêt de tous les threads du
processus.
L'argument attr pointe sur une structure pthread_attr_t dont le
contenu est utilisé pendant la création des threads pour déterminer les
attributs du nouveau thread. Cette structure est initialisée avec
pthread_attr_init(3) et les fonctions similaires. Si attr est NULL,
alors le thread est créé avec les attributs par défaut.
Avant de rendre la main, un appel réussi à pthread_create() stocke
l'identifiant du nouveau thread dans le tampon pointé par thread. Cet
identifiant est utilisé pour se référer à ce thread dans les appels
ultérieurs aux autres fonctions de pthreads.
Le nouveau thread hérite d'une copie du masque de signal du thread créateur
(pthread_sigmask(3)). L'ensemble des signaux en attente pour le nouveau
thread est vide (sigpending(2)). Le nouveau thread n'hérite pas de la
pile spécifique de signaux (sigaltstack(2)) du thread appelant.
Le nouveau thread hérite de l'environnement en virgule flottante
(fenv(3)) du thread appelant.
La valeur initiale de l'horloge CPU du nouveau thread est 0 (voir
pthread_getcpuclockid(3)).
Détails spécifiques à Linux
Le nouveau thread hérite de copies des ensembles des capacités (voir
capabilities(7)) et des masques d'affinité CPU (consultez
sched_setaffinity(2)) du thread appelant.
VALEUR RENVOYÉE
En cas de réussite, pthread_create() renvoie 0 ; en cas d'erreur, elle
renvoie un numéro d'erreur, et le contenu de *thread est indéfini.
ERREURS
- EAGAIN
-
Ressources insuffisantes pour créer un nouveau thread.
- EAGAIN
-
Une limite système sur le nombre de threads a été atteinte. Plusieurs
limites pourraient déclencher cette erreur : la limite de ressources souple
RLIMIT_NPROC (définie à l’aide setrlimit(2)), qui limite le nombre de
processus et threads par identifiant d’utilisateur réel, a été atteinte ;
la limite système imposée par le noyau sur le nombre total de processus et
threads, /proc/sys/kernel/threads-max, a été atteinte (consultez
proc(5)) ; ou le nombre maximal de PID, /proc/sys/kernel/pid_max, a
été atteint (consultez proc(5)).
- EINVAL
-
Paramètres incorrects dans attr.
-
-
EPERM
Permissions insuffisantes pour définir la politique d'ordonnancement et les
paramètres spécifiés dans attr.
ATTRIBUTS
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
| Interface | Attribut | Valeur
|
|
pthread_create()
| Sécurité des threads | MT-Safe
|
STANDARDS
POSIX.1-2008.
HISTORIQUE
POSIX.1-2001.
NOTES
Consultez pthread_self(3) pour des informations plus détaillées sur
l'identifiant de thread renvoyé dans *thread par
pthread_create(). Sauf si une politique d'ordonnancement temps-réel est
employée, après un appel à pthread_create(), on ne sait pas quel thread
--- l'appelant ou le nouveau thread --- sera exécuté ensuite.
Un thread peut être dans un état soit joignable (joinable), soit détaché
(detached). Si un thread est joignable, un autre thread peut appeler
pthread_join(3) pour attendre que ce thread se termine et récupérer sa
valeur de sortie. Ce n'est que quand un thread terminé et joignable a été
joint que ses ressources sont rendues au système. Quand un thread détaché se
termine, ses ressources sont automatiquement rendues au système : il n'est
pas possible de joindre un tel thread afin d'en obtenir la valeur de
sortie. Mettre un thread dans l'état détaché est pratique pour certains
types de threads de démon dont l'application n'a pas à se préoccuper de la
valeur de sortie. Par défaut, un nouveau thread est créé dans l'état
joignable, à moins qu'attr n'ait été modifié (avec
pthread_attr_setdetachstate(3)) pour créer le thread dans un état
détaché.
Avec l'implémentation NPTL, si la limite souple RLIMIT_STACK a une valeur
autre qu'« unlimited » au moment où le programme a démarré, elle
détermine la taille de la pile par défaut pour les nouveaux threads. Afin
d'obtenir une taille de pile différente de la valeur par défaut, il faut
appeler pthread_attr_setstacksize(3) avec la valeur souhaitée sur
l'argument attr utilisé pour créer un thread. Si la limite de ressources
RLIMIT_STACK a la valeur « unlimited », une valeur dépendant de
l'architecture est utilisée pour la taille de la pile : 2 Mo pour la plupart
des architectures ; 4 Mo pour POWER et Sparc-64.
BOGUES
Dans l'implémentation obsolète LinuxThreads, chacun des threads dans un
processus a un identifiant de processus différent, ce qui est en violation
des spécifications POSIX sur les threads et est la cause de nombreuses
non-conformité au standard. Consultez pthreads(7).
EXEMPLES
Le programme ci-dessous montre l'utilisation de pthread_create(), ainsi
qu'un certain nombre d'autres fonctions de l'API pthreads.
Lors de l'exécution suivante, sur un système avec l'implémentation NPTL, la
taille de la pile vaut par défaut la valeur renvoyée par la limite de la
ressource « stack size » (taille de la pile) :
$ ulimit -s
8192 # The stack size limit is 8 MB (0x800000 bytes)
$ ./a.out hola salut servus
Thread 1: top of stack near 0xb7dd03b8; argv_string=hola
Thread 2: top of stack near 0xb75cf3b8; argv_string=salut
Thread 3: top of stack near 0xb6dce3b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS
Lors de l'exécution suivante, le programme définit explicitement une taille
de pile de 1 Mo (avec pthread_attr_setstacksize(3)) pour les threads
créés :
$ ./a.out -s 0x100000 hola salut servus
Thread 1: top of stack near 0xb7d723b8; argv_string=hola
Thread 2: top of stack near 0xb7c713b8; argv_string=salut
Thread 3: top of stack near 0xb7b703b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS
Source du programme
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
int thread_num; /* Application-defined thread # */
char *argv_string; /* From command-line argument */
};
/* Thread start function: display address near top of our stack,
and return upper-cased copy of argv_string. */
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = arg;
char *uargv;
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, (void *) &tinfo, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (char *p = uargv; *p != '\0'; p++)
*p = toupper(*p);
return uargv;
}
int
main(int argc, char *argv[])
{
int s, opt;
void *res;
size_t num_threads;
ssize_t stack_size;
pthread_attr_t attr;
struct thread_info *tinfo;
/* The "-s" option specifies a stack size for our threads. */
stack_size = -1;
while ((opt = getopt(argc, argv, "s:")) != -1) {
switch (opt) {
case 's':
stack_size = strtoul(optarg, NULL, 0);
break;
default:
fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
argv[0]);
exit(EXIT_FAILURE);
}
}
num_threads = argc - optind;
/* Initialize thread creation attributes. */
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");
if (stack_size > 0) {
s = pthread_attr_setstacksize(&attr, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
/* Allocate memory for pthread_create() arguments. */
tinfo = calloc(num_threads, sizeof(*tinfo));
if (tinfo == NULL)
handle_error("calloc");
/* Create one thread for each command-line argument. */
for (size_t tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].argv_string = argv[optind + tnum];
/* The pthread_create() call stores the thread ID into
corresponding element of tinfo[]. */
s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &tinfo[tnum]);
if (s != 0)
handle_error_en(s, "pthread_create");
}
/* Destroy the thread attributes object, since it is no
longer needed. */
s = pthread_attr_destroy(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy");
/* Now join with each thread, and display its returned value. */
for (size_t tnum = 0; tnum < num_threads; tnum++) {
s = pthread_join(tinfo[tnum].thread_id, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
printf("Joined with thread %d; returned value was %s\n",
tinfo[tnum].thread_num, (char *) res);
free(res); /* Free memory allocated by thread */
}
free(tinfo);
exit(EXIT_SUCCESS);
}
VOIR AUSSI
getrlimit(2), pthread_attr_init(3), pthread_cancel(3),
pthread_detach(3), pthread_equal(3), pthread_exit(3),
pthread_getattr_np(3), pthread_join(3), pthread_self(3),
pthread_setattr_default_np(3), pthreads(7)
TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess <https://www.blaess.fr/christophe/>,
Stéphan Rafin <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>,
Frédéric Hantrais <fhantrais@gmail.com>
et
Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>
Cette traduction est une documentation libre ; veuillez vous reporter à la
GNU General Public License version 3
concernant les conditions de copie et
de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- Détails spécifiques à Linux
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- ATTRIBUTS
-
- STANDARDS
-
- HISTORIQUE
-
- NOTES
-
- BOGUES
-
- EXEMPLES
-
- Source du programme
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 05:06:22 GMT, September 19, 2025