Provided by: manpages-ru_4.19.0-7_all bug

ИМЯ

       pthreads - нити POSIX

ОПИСАНИЕ

       В  POSIX.1  определён набор интерфейсов (функции, заголовочные файлы) для работы с нитями,
       более известными как нити POSIX или Pthreads. В одном процессе может быть несколько нитей,
       которые выполняют одну программу. Эти нити работают с общей глобальной памятью (сегментами
       данных и кучи), но у каждой нити есть собственный стек (автоматические переменные).

       Также, в POSIX.1 требуется, чтобы нити имели общий диапазон других атрибутов (т.  е.,  эти
       атрибуты процесса, а не нити):

       •  идентификатор процесса

       •  идентификатор родительского процесса

       •  Идентификатор группы процессов и сеанса

       •  Управляющий терминал

       •  Идентификаторы пользователя и группы

       •  Открытые файловые дескрипторы

       •  Обычные блокировки (смотрите fcntl(2))

       •  Обработчики сигналов

       •  Маска создания режима доступа к файлу (umask(2))

       •  Текущий каталог (chdir(2)) и корневой каталог (chroot(2))

       •  Интервальные таймеры (setitimer(2)) и таймеры POSIX (timer_create(2))

       •  Значение уступчивости (setpriority(2))

       •  Ограничения по ресурсам (setrlimit(2))

       •  Измерители потребления времени ЦП (times(2)) и ресурсов (getrusage(2))

       Как и для стека, в POSIX.1 определены другие атрибуты, которые уникальны в каждой нити:

       •  Идентификатор нити (тип данных pthread_t)

       •  Маска сигналов (pthread_sigmask(3))

       •  Переменная errno

       •  Альтернативный стек сигнала (sigaltstack(2))

       •  Алгоритм и приоритет планирования реального времени (sched(7))

       Следующие свойства есть только в Linux и также уникальны в каждой нити:

       •  мандаты (смотрите capabilities(7))

       •  Привязка к ЦП (sched_setaffinity(2))

   Возвращаемые значения из функций pthreads
       Most  pthreads  functions  return 0 on success, and an error number on failure.  The error
       numbers that can be returned have the same meaning as the error numbers returned in  errno
       by conventional system calls and C library functions.  Note that the pthreads functions do
       not set errno.  For each of the pthreads functions that can return an error,  POSIX.1-2001
       specifies that the function can never fail with the error EINTR.

   Идентификатор нити
       Каждой нити процесса назначается уникальный идентификатор нити (имеет тип pthread_t). Этот
       идентификатор возвращается вызывающему pthread_create(3), а в самой нити её  идентификатор
       можно получить с помощью pthread_self(3).

       Внутри  процесса  гарантируется  уникальность  идентификаторов  нитей  (во  всех  функциях
       pthreads, которые принимают аргумент идентификатора  нити,  подразумевается,  что  указана
       нить из процесса вызывающего).

       Система  может повторно использовать идентификатор нити после объединения завершённой нити
       или отсоединения завершённой нити. В POSIX сказано: «Если приложение пытается использовать
       идентификатор нити, у который закончился срок жизни, то поведение не предсказуемо».

   Нитебезопасные функции
       Нитебезопасная  функция  —  это  функция,  которую  можно безопасно (т. е., это приведёт к
       единым результатам независимо от окружения) вызывать из нескольких нитей одновременно.

       В POSIX.1-2001 и POSIX.1-2008 требуется, чтобы все функции, описанные  в  стандарте,  были
       нитебезопасными, за исключением следующих функций:

           asctime()
           basename()
           catgets()
           crypt()
           ctermid() if passed a non-NULL argument
           ctime()
           dbm_clearerr()
           dbm_close()
           dbm_delete()
           dbm_error()
           dbm_fetch()
           dbm_firstkey()
           dbm_nextkey()
           dbm_open()
           dbm_store()
           dirname()
           dlerror()
           drand48()
           ecvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           encrypt()
           endgrent()
           endpwent()
           endutxent()
           fcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           ftw()
           gcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           getc_unlocked()
           getchar_unlocked()
           getdate()
           getenv()
           getgrent()
           getgrgid()
           getgrnam()
           gethostbyaddr() [POSIX.1-2001 only (function removed in
                            POSIX.1-2008)]
           gethostbyname() [POSIX.1-2001 only (function removed in
                            POSIX.1-2008)]
           gethostent()
           getlogin()
           getnetbyaddr()
           getnetbyname()
           getnetent()
           getopt()
           getprotobyname()
           getprotobynumber()
           getprotoent()
           getpwent()
           getpwnam()
           getpwuid()
           getservbyname()
           getservbyport()
           getservent()
           getutxent()
           getutxid()
           getutxline()
           gmtime()
           hcreate()
           hdestroy()
           hsearch()
           inet_ntoa()
           l64a()
           lgamma()
           lgammaf()
           lgammal()
           localeconv()
           localtime()
           lrand48()
           mrand48()
           nftw()
           nl_langinfo()
           ptsname()
           putc_unlocked()
           putchar_unlocked()
           putenv()
           pututxline()
           rand()
           readdir()
           setenv()
           setgrent()
           setkey()
           setpwent()
           setutxent()
           strerror()
           strsignal() [Added in POSIX.1-2008]
           strtok()
           system() [Added in POSIX.1-2008]
           tmpnam() if passed a non-NULL argument
           ttyname()
           unsetenv()
           wcrtomb() if its final argument is NULL
           wcsrtombs() if its final argument is NULL
           wcstombs()
           wctomb()

   Безопасные асинхронные отменяемые функции
       Безопасная  асинхронная  отменяемая  функция  (async-cancel-safe  function) — это функция,
       которую можно безопасно вызывать в приложении,  в  котором  разрешено  асинхронная  отмена
       (смотрите pthread_setcancelstate(3)).

       Согласно  POSIX.1-2001  и  POSIX.1-2008  только  следующие функции должны быть безопасными
       асинхронными отменяемыми:

           pthread_cancel()
           pthread_setcancelstate()
           pthread_setcanceltype()

   Точки отмены
       POSIX.1 specifies that certain  functions  must,  and  certain  other  functions  may,  be
       cancelation  points.  If a thread is cancelable, its cancelability type is deferred, and a
       cancelation request is pending for the thread, then the thread is canceled when it calls a
       function that is a cancelation point.

       The  following  functions  are  required  to  be cancelation points by POSIX.1-2001 and/or
       POSIX.1-2008:

           accept()
           aio_suspend()
           clock_nanosleep()
           close()
           connect()
           creat()
           fcntl() F_SETLKW
           fdatasync()
           fsync()
           getmsg()
           getpmsg()
           lockf() F_LOCK
           mq_receive()
           mq_send()
           mq_timedreceive()
           mq_timedsend()
           msgrcv()
           msgsnd()
           msync()
           nanosleep()
           open()
           openat() [добавлена в POSIX.1-2008]
           pause()
           poll()
           pread()
           pselect()
           pthread_cond_timedwait()
           pthread_cond_wait()
           pthread_join()
           pthread_testcancel()
           putmsg()
           putpmsg()
           pwrite()
           read()
           readv()
           recv()
           recvfrom()
           recvmsg()
           select()
           sem_timedwait()
           sem_wait()
           send()
           sendmsg()
           sendto()
           sigpause() [только POSIX.1-2001 (перемещена в список «может» в POSIX.1-2008)]
           sigsuspend()
           sigtimedwait()
           sigwait()
           sigwaitinfo()
           sleep()
           system()
           tcdrain()
           usleep() [только POSIX.1-2001 (функция удалена в POSIX.1-2008)]
           wait()
           waitid()
           waitpid()
           write()
           writev()

       The following functions  may  be  cancelation  points  according  to  POSIX.1-2001  and/or
       POSIX.1-2008:

           access()
           asctime()
           asctime_r()
           catclose()
           catgets()
           catopen()
           chmod() [Added in POSIX.1-2008]
           chown() [Added in POSIX.1-2008]
           closedir()
           closelog()
           ctermid()
           ctime()
           ctime_r()
           dbm_close()
           dbm_delete()
           dbm_fetch()
           dbm_nextkey()
           dbm_open()
           dbm_store()
           dlclose()
           dlopen()
           dprintf() [Added in POSIX.1-2008]
           endgrent()
           endhostent()
           endnetent()
           endprotoent()
           endpwent()
           endservent()
           endutxent()
           faccessat() [Added in POSIX.1-2008]
           fchmod() [Added in POSIX.1-2008]
           fchmodat() [Added in POSIX.1-2008]
           fchown() [Added in POSIX.1-2008]
           fchownat() [Added in POSIX.1-2008]
           fclose()
           fcntl() (for any value of cmd argument)
           fflush()
           fgetc()
           fgetpos()
           fgets()
           fgetwc()
           fgetws()
           fmtmsg()
           fopen()
           fpathconf()
           fprintf()
           fputc()
           fputs()
           fputwc()
           fputws()
           fread()
           freopen()
           fscanf()
           fseek()
           fseeko()
           fsetpos()
           fstat()
           fstatat() [Added in POSIX.1-2008]
           ftell()
           ftello()
           ftw()
           futimens() [Added in POSIX.1-2008]
           fwprintf()
           fwrite()
           fwscanf()
           getaddrinfo()
           getc()
           getc_unlocked()
           getchar()
           getchar_unlocked()
           getcwd()
           getdate()
           getdelim() [Added in POSIX.1-2008]
           getgrent()
           getgrgid()
           getgrgid_r()
           getgrnam()
           getgrnam_r()
           gethostbyaddr() [POSIX.1-2001 only (function removed in
                            POSIX.1-2008)]
           gethostbyname() [POSIX.1-2001 only (function removed in
                            POSIX.1-2008)]
           gethostent()
           gethostid()
           gethostname()
           getline() [Added in POSIX.1-2008]
           getlogin()
           getlogin_r()
           getnameinfo()
           getnetbyaddr()
           getnetbyname()
           getnetent()
           getopt() (if opterr is nonzero)
           getprotobyname()
           getprotobynumber()
           getprotoent()
           getpwent()
           getpwnam()
           getpwnam_r()
           getpwuid()
           getpwuid_r()
           gets()
           getservbyname()
           getservbyport()
           getservent()
           getutxent()
           getutxid()
           getutxline()
           getwc()
           getwchar()
           getwd() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           glob()
           iconv_close()
           iconv_open()
           ioctl()
           link()
           linkat() [Added in POSIX.1-2008]
           lio_listio() [Added in POSIX.1-2008]
           localtime()
           localtime_r()
           lockf() [Added in POSIX.1-2008]
           lseek()
           lstat()
           mkdir() [Added in POSIX.1-2008]
           mkdirat() [Added in POSIX.1-2008]
           mkdtemp() [Added in POSIX.1-2008]
           mkfifo() [Added in POSIX.1-2008]
           mkfifoat() [Added in POSIX.1-2008]
           mknod() [Added in POSIX.1-2008]
           mknodat() [Added in POSIX.1-2008]
           mkstemp()
           mktime()
           nftw()
           opendir()
           openlog()
           pathconf()
           pclose()
           perror()
           popen()
           posix_fadvise()
           posix_fallocate()
           posix_madvise()
           posix_openpt()
           posix_spawn()
           posix_spawnp()
           posix_trace_clear()
           posix_trace_close()
           posix_trace_create()
           posix_trace_create_withlog()
           posix_trace_eventtypelist_getnext_id()
           posix_trace_eventtypelist_rewind()
           posix_trace_flush()
           posix_trace_get_attr()
           posix_trace_get_filter()
           posix_trace_get_status()
           posix_trace_getnext_event()
           posix_trace_open()
           posix_trace_rewind()
           posix_trace_set_filter()
           posix_trace_shutdown()
           posix_trace_timedgetnext_event()
           posix_typed_mem_open()
           printf()
           psiginfo() [Added in POSIX.1-2008]
           psignal() [Added in POSIX.1-2008]
           pthread_rwlock_rdlock()
           pthread_rwlock_timedrdlock()
           pthread_rwlock_timedwrlock()
           pthread_rwlock_wrlock()
           putc()
           putc_unlocked()
           putchar()
           putchar_unlocked()
           puts()
           pututxline()
           putwc()
           putwchar()
           readdir()
           readdir_r()
           readlink() [Added in POSIX.1-2008]
           readlinkat() [Added in POSIX.1-2008]
           remove()
           rename()
           renameat() [Added in POSIX.1-2008]
           rewind()
           rewinddir()
           scandir() [Added in POSIX.1-2008]
           scanf()
           seekdir()
           semop()
           setgrent()
           sethostent()
           setnetent()
           setprotoent()
           setpwent()
           setservent()
           setutxent()
           sigpause() [Added in POSIX.1-2008]
           stat()
           strerror()
           strerror_r()
           strftime()
           symlink()
           symlinkat() [Added in POSIX.1-2008]
           sync()
           syslog()
           tmpfile()
           tmpnam()
           ttyname()
           ttyname_r()
           tzset()
           ungetc()
           ungetwc()
           unlink()
           unlinkat() [Added in POSIX.1-2008]
           utime() [Added in POSIX.1-2008]
           utimensat() [Added in POSIX.1-2008]
           utimes() [Added in POSIX.1-2008]
           vdprintf() [Added in POSIX.1-2008]
           vfprintf()
           vfwprintf()
           vprintf()
           vwprintf()
           wcsftime()
           wordexp()
           wprintf()
           wscanf()

       An  implementation  may  also  mark  other  functions  not  specified  in  the standard as
       cancelation points.  In particular, an implementation is likely to  mark  any  nonstandard
       function  that  may  block as a cancelation point.  (This includes most functions that can
       touch files.)

       It should be noted that even if an application is not using asynchronous cancelation, that
       calling  a  function from the above list from an asynchronous signal handler may cause the
       equivalent  of  asynchronous  cancelation.   The  underlying  user  code  may  not  expect
       asynchronous  cancelation  and  the  state  of  the  user  data  may  become inconsistent.
       Therefore signals should  be  used  with  caution  when  entering  a  region  of  deferred
       cancelation.

   Компиляция в Linux
       В  Linux, программы, использующие программный интерфейс pthreads, должны компилироваться с
       помощью cc -pthread.

   Реализации нитей POSIX в Linux
       За всё время в библиотеке GNU C было две реализации нитей для Linux:

       LinuxThreads
              Первоначальная реализация pthreads. Начиная с glibc 2.4 эта  реализация  больше  не
              поддерживается.

       NPTL (библиотека нитей POSIX)
              Современная  реализация  pthreads.  По  сравнению  с LinuxThreads, NPTL более точно
              соответствует требованиям POSIX.1 и более  производительна  при  создании  большого
              количества  нитей.  NPTL  появилась  в  glibc  начиная  с  версии  2.3.2, и требует
              свойства, появившиеся в ядре Linux 2.6.

       Обе  реализации  являются,  так  называемыми  реализациями  1:1,  то  есть   каждая   нить
       отображается  в планируемый элемента ядра. Обе реализации используют системный вызов Linux
       clone(2). В NPTL примитивы синхронизации нитей  (мьютексы,  объединение  нитей  и  т  .п.)
       реализованы с помощью системного вызова Linux futex(2).

   LinuxThreads
       Отличительные свойства данной реализации:

       •  В   дополнении   к  главной  (начальной)  нити,  нити  программы  создаются  с  помощью
          pthread_create(3), реализация создаёт «управляющую» нить. Эта нить выполняет создание и
          завершение нитей (что приводит к проблемам, если эта нить случайно завершится).

       •  Внутри  реализации  используются  сигналы.  В Linux 2.2 и новее используются первые три
          сигнала реального времени (смотрите также signal(7)). В старых ядрах Linux используются
          сигналы   SIGUSR1   и  SIGUSR2.  В  приложениях  нельзя  использовать  набор  сигналов,
          задействованный в реализации.

       •  У нитей разные ID процесса (фактически, нити LinuxThreads реализованы как  процессы,  у
          которых  больше  общей  информации  чем  обычно, но которые имеют разный идентификаторы
          процесса). Нити LinuxThreads (включая управляющую нить) в ps(1)  видимы  как  отдельные
          процессы.

       Реализация LinuxThreads отклоняется от спецификации POSIX.1 в нескольких местах, а именно:

       •  Вызов getpid(2) возвращает разные значения для каждой нити.

       •  Вызов  getppid(2) в нитях, кроме главной, возвращает идентификатор процесса управляющей
          нити; вместо getppid(2) в этих  нитях  будет  возвращаться  тоже  значение,  что  и  из
          getppid(2) в главной нити.

       •  Когда  нить  создаёт  новый  процесс-потомок с помощью fork(2), все нити должны ожидать
          потомка в wait(2). Однако реализация позволяет вызвать wait(2) только в  нити,  которая
          создала потомка.

       •  Когда  нить  вызывает  execve(2), остальные нити завершают работу (требование POSIX.1).
          Однако, получаемый процесс имеет тот же PID, что и нить, которая вызвала execve(2): это
          должен быть тот же PID, что и у главной нити.

       •  У  нитей  разные  ID  пользователя и группы. Это может вызвать сложности в программах с
          set-user-ID и может привести к ошибкам функций pthreads, если приложение изменяет  свои
          учётные данные с помощью seteuid(2) и подобных вызовов.

       •  У нитей разные ID сеанса и группы процессов.

       •  У нитей разные записи о блокировках, созданных fcntl(2).

       •  Информация,  возвращаемая  times(2)  и  getrusage(2),  относится  только к нити, а не к
          процессу в целом.

       •  У нитей разные значения отмен семафоров (смотрите semop(2)).

       •  У нитей разные интервалы таймеров.

       •  У нитей разные значения уступчивости.

       •  В POSIX.1 различаются  сигналы,  адресованные  процессу  в  целом  и  отдельным  нитям.
          Согласно  POSIX.1,  сигналы,  направленные  процессу  (посланные,  например,  с помощью
          kill(2)), должны обрабатываться одной  произвольно  выбранной  нитью  внутри  процесса.
          LinuxThreads  не  поддерживает сигналы, направленные процессу: сигналы могут посылаться
          только определённым нитям.

       •  Нити имеют разные настройки альтернативного стека  сигналов.  Однако,  новые  настройки
          альтернативного  стека  сигналов  копируются  из  нити,  которая  его  создаёт, так что
          изначально  нити  имеют  единый  альтернативный  стек  сигналов  (новая   нить   должна
          запускаться  без  альтернативного  стека сигналов. Если две нити обрабатывают сигналы в
          едином  альтернативном  стеке  сигналов  одновременно,   то   в   программе   возникнет
          непредсказуемая ошибка).

   NPTL
       В NPTL все нити процесса помещаются в одну группу нитей; все члены группы нитей имеют один
       PID. В NPTL нет управляющей нити.

       Внутри NPTL  используются  первые  два  сигнала  реального  времени;  эти  сигналы  нельзя
       использовать в приложениях. Подробности смотрите в nptl(7).

       NPTL тоже не соответствует POSIX.1, как минимум, в одном:

       •  У нитей разные значения уступчивости.

       Несколько несоответствий NPTL проявляется только при работе со старыми ядрами:

       •  The  information  returned  by  times(2)   and  getrusage(2)  is per-thread rather than
          process-wide (fixed in Linux 2.6.9).

       •  Threads do not share resource limits (fixed in Linux 2.6.10).

       •  Threads do not share interval timers (fixed in Linux 2.6.12).

       •  Only the main thread is permitted to start a new  session  using  setsid(2)  (fixed  in
          Linux 2.6.16).

       •  Only the main thread is permitted to make the process into a process group leader using
          setpgid(2)  (fixed in Linux 2.6.16).

       •  Threads have distinct  alternate  signal  stack  settings.   However,  a  new  thread's
          alternate signal stack settings are copied from the thread that created it, so that the
          threads initially share an alternate signal stack (fixed in Linux 2.6.16).

       Также стоит учитывать следующее о реализации NPTL:

       •  Если мягкое ограничение ресурса на  размер  стека  (смотрите  описание  RLIMIT_STACK  в
          setrlimit(2))  устанавливается  в  значение,  отличное  от  unlimited,  то это значение
          определяет размер стека по умолчанию  для  новых  нитей.  В  целях  эффективности,  это
          ограничение  должно  быть  установлено  но  выполнения  программы,  возможно  с помощью
          встроенной команды оболочки ulimit -s (limit stacksize в оболочке C).

   Определение реализации нитей
       Начиная с glibc 2.3.2, для определение  реализации  нитей  в  системе  можно  использовать
       команду getconf(1), например:

           bash$ getconf GNU_LIBPTHREAD_VERSION
           NPTL 2.3.4

       При наличии старых версий glibc можно использовать команду:

           bash$ $( ldd /bin/ls | grep libc.so | awk '{print $3}' ) | \
                           egrep -i 'threads|nptl'
                   Native POSIX Threads Library by Ulrich Drepper et al

   Выбор реализации нитей: LD_ASSUME_KERNEL
       В  системах  с  glibc, которая поддерживает и LinuxThreads и NPTL (например, glibc 2.3.x),
       можно  воспользоваться  переменной  окружения  LD_ASSUME_KERNEL   для   замены   выбранной
       динамическим  компоновщиков  реализации  нитей  по  умолчанию.  Эта  переменная  указывает
       динамическому компоновщику считать, что он  запускается  с  определённой  версией  ядра  в
       системе.  Указав  версию ядра, в которой не поддержки, требуемой NPTL, его можно заставить
       использовать LinuxThreads (наиболее  вероятной  причиной  для  этого  будет  необходимость
       запуска  (сломанного)  приложения, которое зависит от некоторого не совместимого поведения
       LinuxThreads). Пример:

           bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \
                           awk '{print $3}' ) | egrep -i 'threads|nptl'
                   linuxthreads-0.10 by Xavier Leroy

СМ. ТАКЖЕ

       clone(2), fork(2), futex(2), gettid(2), proc(5), attributes(7), futex(7), nptl(7),
       sigevent(7), signal(7)

       Различные справочные страницы pthreads, например: pthread_atfork(3), pthread_attr_init(3),
       pthread_cancel(3), pthread_cleanup_push(3), pthread_cond_signal(3), pthread_cond_wait(3),
       pthread_create(3), pthread_detach(3), pthread_equal(3), pthread_exit(3),
       pthread_key_create(3), pthread_kill(3), pthread_mutex_lock(3), pthread_mutex_unlock(3),
       pthread_mutexattr_destroy(3), pthread_mutexattr_init(3), pthread_once(3),
       pthread_spin_init(3), pthread_spin_lock(3), pthread_rwlockattr_setkind_np(3),
       pthread_setcancelstate(3), pthread_setcanceltype(3), pthread_setspecific(3),
       pthread_sigmask(3), pthread_sigqueue(3) и pthread_testcancel(3)

ПЕРЕВОД

       Русский перевод этой страницы руководства был сделан Alexey, Azamat Hackimov
       <azamat.hackimov@gmail.com>, kogamatranslator49 <r.podarov@yandex.ru>, Kogan, Max Is
       <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

       Этот перевод является бесплатной документацией; прочитайте Стандартную общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.