pthread_create(3) Library Functions Manual pthread_create(3) NOM pthread_create - Creer un nouveau thread BIBLIOTHEQUE Bibliotheque de threads POSIX (libpthread, -lpthread) SYNOPSIS #include 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() demarre un nouveau thread (processus leger) dans le processus appelant. Le nouveau thread commence par appeler start_routine() ; arg est passe comme unique argument de start_routine(). Le nouveau thread se termine d'une des manieres suivantes : - Il appelle pthread_exit(3), en indiquant une valeur de sortie qui sera disponible pour un autre thread du meme processus qui appelle pthread_join(3). - Il sort de la routine start_routine(). C'est equivalent a appeler pthread_exit(3) avec la valeur fournie a l'instruction return. - Il est annule (voir pthread_cancel(3)). - Un des threads du processus appelle exit(3) ou le thread principal sort de la routine main() ce qui entraine l'arret de tous les threads du processus. L'argument attr pointe sur une structure pthread_attr_t dont le contenu est utilise pendant la creation des threads pour determiner les attributs du nouveau thread. Cette structure est initialisee avec pthread_attr_init(3) et les fonctions similaires. Si attr est NULL, alors le thread est cree avec les attributs par defaut. Avant de rendre la main, un appel reussi a pthread_create() stocke l'identifiant du nouveau thread dans le tampon pointe par thread. Cet identifiant est utilise pour se referer a ce thread dans les appels ulterieurs aux autres fonctions de pthreads. Le nouveau thread herite d'une copie du masque de signal du thread createur (pthread_sigmask(3)). L'ensemble des signaux en attente pour le nouveau thread est vide (sigpending(2)). Le nouveau thread n'herite pas de la pile specifique de signaux (sigaltstack(2)) du thread appelant. Le nouveau thread herite 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)). Details specifiques a Linux Le nouveau thread herite de copies des ensembles des capacites (voir capabilities(7)) et des masques d'affinite CPU (consultez sched_setaffinity(2)) du thread appelant. VALEUR RENVOYEE En cas de reussite, pthread_create() renvoie 0 ; en cas d'erreur, elle renvoie un numero d'erreur, et le contenu de *thread est indefini. ERREURS EAGAIN Ressources insuffisantes pour creer un nouveau thread. EAGAIN Une limite systeme sur le nombre de threads a ete atteinte. Plusieurs limites pourraient declencher cette erreur : la limite de ressources souple RLIMIT_NPROC (definie a l'aide setrlimit(2)), qui limite le nombre de processus et threads par identifiant d'utilisateur reel, a ete atteinte ; la limite systeme imposee par le noyau sur le nombre total de processus et threads, /proc/sys/kernel/threads-max, a ete atteinte (consultez proc(5)) ; ou le nombre maximal de PID, /proc/sys/kernel/pid_max, a ete atteint (consultez proc(5)). EINVAL Parametres incorrects dans attr. EPERM Permissions insuffisantes pour definir la politique d'ordonnancement et les parametres specifies dans attr. ATTRIBUTS Pour une explication des termes utilises dans cette section, consulter attributes(7). +---------------------------------+--------------------------+---------+ |Interface | Attribut | Valeur | +---------------------------------+--------------------------+---------+ |pthread_create() | Securite des threads | MT-Safe | +---------------------------------+--------------------------+---------+ STANDARDS POSIX.1-2008. HISTORIQUE POSIX.1-2001. NOTES Consultez pthread_self(3) pour des informations plus detaillees sur l'identifiant de thread renvoye dans *thread par pthread_create(). Sauf si une politique d'ordonnancement temps-reel est employee, apres un appel a pthread_create(), on ne sait pas quel thread -- l'appelant ou le nouveau thread -- sera execute ensuite. Un thread peut etre dans un etat soit joignable (joinable), soit detache (detached). Si un thread est joignable, un autre thread peut appeler pthread_join(3) pour attendre que ce thread se termine et recuperer sa valeur de sortie. Ce n'est que quand un thread termine et joignable a ete joint que ses ressources sont rendues au systeme. Quand un thread detache se termine, ses ressources sont automatiquement rendues au systeme : il n'est pas possible de joindre un tel thread afin d'en obtenir la valeur de sortie. Mettre un thread dans l'etat detache est pratique pour certains types de threads de demon dont l'application n'a pas a se preoccuper de la valeur de sortie. Par defaut, un nouveau thread est cree dans l'etat joignable, a moins qu'attr n'ait ete modifie (avec pthread_attr_setdetachstate(3)) pour creer le thread dans un etat detache. Under the NPTL threading implementation, if the RLIMIT_STACK soft resource limit at the time the program started has any value other than "unlimited", then it determines the default stack size of new threads. Using pthread_attr_setstacksize(3), the stack size attribute can be explicitly set in the attr argument used to create a thread, in order to obtain a stack size other than the default. If the RLIMIT_STACK resource limit is set to "unlimited", a per-architecture value is used for the stack size: 2 MB on most architectures; 4 MB on POWER and Sparc-64. BOGUES Dans l'implementation obsolete LinuxThreads, chacun des threads dans un processus a un identifiant de processus different, ce qui est en violation des specifications POSIX sur les threads et est la cause de nombreuses non-conformite 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'execution suivante, sur un systeme avec l'implementation NPTL, la taille de la pile vaut par defaut la valeur renvoyee 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'execution suivante, le programme definit explicitement une taille de pile de 1 Mo (avec pthread_attr_setstacksize(3)) pour les threads crees : $ ./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 #include #include #include #include #include #include #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 { /* Utilise comme argument pour thread_start() */ pthread_t thread_id; /* Identifiant renvoye par pthread_create() */ int thread_num; /* N de thread defini par l'application */ char *argv_string; /* A partir de l'argument en ligne de commande */ }; /* Fonction de demarrage du thread : affiche l'adresse vers le haut de la pile, et renvoie une copie en majuscule de argv_string. */ static void * thread_start(void *arg) { struct thread_info *tinfo = arg; char *uargv; printf("Thread %d : sommet de la pile pres de %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; /* L'option "-s" specifie une taille de pile pour les 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; /* Initialiser les attributs de creation de thread. */ 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"); } /* Allouer la memoire pour les arguments de pthread_create(). */ tinfo = calloc(num_threads, sizeof(*tinfo)); if (tinfo == NULL) handle_error("calloc"); /* Creer un thread pour chaque argument en ligne de commande. */ for (size_t tnum = 0; tnum < num_threads; tnum++) { tinfo[tnum].thread_num = tnum + 1; tinfo[tnum].argv_string = argv[optind + tnum]; /* L'appel pthread_create() stocke l'identifiant du thread dans l'element correspondant de tinfo[]. */ s = pthread_create(&tinfo[tnum].thread_id, &attr, &thread_start, &tinfo[tnum]); if (s != 0) handle_error_en(s, "pthread_create"); } /* Detruire l'objet des attributs du thread dans la mesure ou il n'est plus necessaire. */ s = pthread_attr_destroy(&attr); if (s != 0) handle_error_en(s, "pthread_attr_destroy"); /* Maintenant joindre chaque thread et afficher la valeur qu'il renvoie. */ 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("Thread joint %d ; la valeur renvoyee est %s\n", tinfo[tnum].thread_num, (char *) res); free(res); /* Liberer la memoire allouee par 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 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- Pierre Giraud 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 12 fevrier 2024 pthread_create(3)