NOM¶
pthread_create - Créer un nouveau thread
SYNOPSIS¶
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compilez et effectuez l'édition des liens avec l'option
-pthread.
DESCRIPTION¶
La fonction
pthread_create() démarre un nouveau thread 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 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(). Cela entraine 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 revenir, 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)).
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, ou une
limite sur le nombre de threads imposée par le système a
été atteinte. Ce dernier cas peut arriver de deux
façons : la limite souple RLIMIT_NPROC
(changée par setrlimit(2)), qui limite le nombre de
processus pour un identifiant d'utilisateur réel, a
été atteinte ; ou alors la limite imposée par
le noyau sur le nombre total de threads,
/proc/sys/kernel/threads-max, a été atteinte.
- EINVAL
- Paramètres invalides dans attr.
- EPERM
- Permissions insuffisantes pour définir la politique
d'ordonnancement et les paramètres spécifiés dans
attr.
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
démons qui ne se préoccupent pas de la valeur de sortie de ses
threads. 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é.
Sous Linux/x86-32, la taille de la pile par défaut pour un nouveau thread
est de 2 mégaoctets. 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é, alors 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.
BOGUES¶
Dans l'implémentation obsolète LinuxThreads, chacun des threads
dans un processus a un identifiant de processus différent. Ceci est en
violation des spécifications POSIX sur les threads, et est la cause de
beaucoup de non conformité au standard. Consultez
pthreads(7).
EXEMPLE¶
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 <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.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, *p;
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, &p, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (p = uargv; *p != '\0'; p++)
*p = toupper(*p);
return uargv;
}
int
main(int argc, char *argv[])
{
int s, tnum, opt, num_threads;
struct thread_info *tinfo;
pthread_attr_t attr;
int stack_size;
void *res;
/* 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(struct thread_info));
if (tinfo == NULL)
handle_error("calloc");
/* Create one thread for each command-line argument */
for (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 (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),
pthreads(7)
COLOPHON¶
Cette page fait partie de la publication 3.65 du projet
man-pages Linux.
Une description du projet et des instructions pour signaler des anomalies
peuvent être trouvées à l'adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION¶
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
<
http://po4a.alioth.debian.org/> par l'équipe de traduction
francophone au sein du projet perkamon
<
http://perkamon.alioth.debian.org/>.
Denis Barbier (2010).
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet
manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce
document en utilisant la commande «
man -L C
<section>
<page_de_man> ».