pthread_create(3) Library Functions Manual pthread_create(3) pthread_create - LIBRARY POSIX threads library (libpthread, -lpthread) #include int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg); pthread_create() . start_routine(); arg start_routine(). : o pthread_exit(3), , , pthread_join(3). o start_routine(). pthread_exit(3) , return. o ( pthread_cancel(3)). o exit(3), main(). . attr pthread_attr_t, ; pthread_attr_init(3) . attr NULL, . pthread_create() ID , thread; pthreads. (pthread_sigmask(3)). (sigpending(2)). (sigaltstack(2)). (fenv(3)). 0 ( pthread_getcpuclockid(3)). , Linux ( capabilities(7)) ( sched_setaffinity(2)). pthread_create() 0; , *thread . EAGAIN . EAGAIN . , : RLIMIT_NPROC ( setrlimit(2)), ID ; , /proc/sys/kernel/threads-max ( proc(5)); PID, /proc/sys/kernel/pid_max ( proc(5)). EINVAL attr. EPERM , attr. attributes(7). +----------------------------+----------------------------------------------------------+--------------------------+ | | | | +----------------------------+----------------------------------------------------------+--------------------------+ |pthread_create() | | MT-Safe | +----------------------------+----------------------------------------------------------+--------------------------+ POSIX.1-2008. POSIX.1-2001. See pthread_self(3) for further information on the thread ID returned in *thread by pthread_create(). Unless real-time scheduling policies are being employed, after a call to pthread_create(), it is indeterminate which thread--the caller or the new thread--will next execute. (joinable) (detached). , pthread_join(3) . . , : . , . , attr ( pthread_attr_setdetachstate(3)). 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. LinuxThreads ID . POSIX ; pthreads(7). pthread_create(), pthreads. NPTL << >>: $ ulimit -s 8192 # 8 (0x800000 ) $ ./a.out hola salut servus 1: 0xb7dd03b8; argv_string=hola 2: 0xb75cf3b8; argv_string=salut 3: 0xb6dce3b8; argv_string=servus 1; HOLA 2; SALUT 3; SERVUS 1 ( pthread_attr_setstacksize(3)) : $ ./a.out -s 0x100000 hola salut servus 1: 0xb7d723b8; argv_string=hola 2: 0xb7c713b8; argv_string=salut 3: 0xb7b703b8; argv_string=servus 1; HOLA 2; SALUT 3; SERVUS #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 { /* 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); } . 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) Alexey, Azamat Hackimov , kogamatranslator49 , Kogan, Max Is , Yuri Kozlov ; GNU 3 , . . , , . Linux man-pages 6.06 12 2024 . pthread_create(3)