Provided by: manpages-ru-dev_4.27.0-1_all bug

НАИМЕНОВАНИЕ

       pthread_create - создаёт новую нить

БИБЛИОТЕКА

       Библиотека потоков POSIX (libpthread, -lpthread)

ОБЗОР

       #include <pthread.h>

       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().

       Новая нить завершает работу в одном из следующих случаев:

       •  Она вызывает pthread_exit(3), указывая код выхода, доступное другой нити в том же процессе,  вызвавшей
          pthread_join(3).

       •  При  возврате  из  start_routine(). Это эквивалентно вызову pthread_exit(3) со значением, переданным в
          операторе return.

       •  При её отмене (смотрите pthread_cancel(3)).

       •  При вызове из любой нити процесса функции 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 <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);
       }

СМОТРИТЕ ТАКЖЕ

       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
       <azamat.hackimov@gmail.com>, kogamatranslator49 <r.podarov@yandex.ru>, Darima Kogan
       <silverdk99@gmail.com>, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов
       <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>

       Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной
       лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или
       более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

       Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом
       разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских
       переводчиков.

Справочные страницы Linux 6.9.1                  15 июня 2024 г.                               pthread_create(3)