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

ИМЯ

       fork - создаёт дочерний процесс

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #include <unistd.h>

       pid_t fork(void);

ОПИСАНИЕ

       Вызов  fork()  создаёт  новый  процесс посредством копирования вызывающего процесса. Новый
       процесс считается дочерним процессом. Вызывающий процесс считается родительским процессом.

       Дочерний и родительский процессы находятся в отдельных пространствах памяти.  Сразу  после
       fork()  эти  пространства имеют одинаковое содержимое. Запись в память, отображение файлов
       (mmap(2)) и снятие отображения  (munmap(2)),  выполненных  в  одном  процессе,  ничего  не
       изменяет в другом.

       Дочерний  процесс  является  точной копией родительского процесса за исключением следующих
       моментов:

       •  Потомок имеет  свой  уникальный  идентификатор  процесса,  и  этот  PID  (идентификатор
          процесса)  не  совпадает  ни  с  одним  существующим  идентификатором  группы процессов
          (setpgid(2)) или сеансов.

       •  Идентификатор родительского  процесса  у  потомка  равен  идентификатору  родительского
          процесса.

       •  Потомок не наследует блокировки памяти родителя (mlock(2), mlockall(2)).

       •  Счётчики использования ресурсов (getrusage(2)) и времени ЦП у потомка сброшены в 0.

       •  Набор ожидающих сигналов потомка изначально пуст (sigpending(2)).

       •  Потомок не наследует значения семафоров родителя (semop(2)).

       •  Потомок  не  наследует  связанные  с процессом блокировки родителя (fcntl(2)) (с другой
          стороны, он наследует блокировки файловых описаний fcntl(2) и блокировки flock(2)).

       •  Потомок не наследует таймеры родителя (setitimer(2), alarm(2), timer_create(2)).

       •  Потомок  не  наследует  ожидающие   выполнения   операции   асинхронного   ввода-вывода
          (aio_read(3),   aio_write(3))  и  контексты  асинхронного  ввода-вывода  родителя  (см.
          io_setup(2)).

       Все перечисленные атрибуты указаны в POSIX.1.  Родитель  и  потомок  также  отличаются  по
       следующим атрибутам процесса, которые есть только в Linux:

       •  Потомок  не  наследует  уведомления  об изменении каталога (dnotify) родителя (смотрите
          описание F_NOTIFY в fcntl(2)).

       •  Настройка PR_SET_PDEATHSIG у prctl(2) сбрасывается,  и  поэтому  потомок  не  принимает
          сигнал о завершении работы родителя.

       •  Резервное   значение   по   умолчанию  устанавливается  равным  родительскому  текущему
          резервному значению таймера. Смотрите описание PR_SET_TIMERSLACK в prctl(2).

       •  Отображение памяти, помеченное с помощью  флага  MADV_DONTFORK  через  madvise(2),  при
          fork() не наследуется.

       •  Память  в  диапазонах  адресов,  которые  были  помечены  с  помощью  madvise(2) флагом
          MADV_WIPEONFORK, обнуляются в потомке после fork()  (флаг  MADV_WIPEONFORK  остаётся  в
          потомке у этих диапазонов адресов).

       •  Сигнал завершения работы потомка всегда SIGCHLD (см. clone(2)).

       •  Биты  прав доступа к порту, установленные с помощью ioperm(2), не наследуются потомком;
          потомок должен установить все нужные ему биты с помощью ioperm(2).

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

       •  The child process is created with a single thread—the  one  that  called  fork().   The
          entire  virtual  address  space of the parent is replicated in the child, including the
          states of mutexes,  condition  variables,  and  other  pthreads  objects;  the  use  of
          pthread_atfork(3)  may be helpful for dealing with problems that this can cause.

       •  В   многонитевой  программе  после  fork()  потомок  может  безопасно  вызывать  только
          безопасные-асинхронные-сигнальные функции (смотрите signal-safety(7)) до тех пор,  пока
          не вызовет execve(2).

       •  Потомок наследует копии набора открытых файловых дескрипторов родителя. Каждый файловый
          дескриптор в потомке ссылается на  то  же  описание  файла  что  и  родитель  (смотрите
          open(2)).  Это  означает,  что  два  файловых  дескриптора  совместно  используют флаги
          состояния  открытого  файла,  смещение  файла  и  атрибуты  ввода-вывода,   управляемые
          сигналами (смотрите описание F_SETOWN и F_SETSIG в fcntl(2)).

       •  Потомок  наследует  копии  набора  файловых  дескрипторов  открытых  очередей сообщений
          родителя (смотрите mq_overview(7)). Каждый файловый дескриптор в потомке  ссылается  на
          то  же  описание  открытой  очереди  сообщений  что  и  родитель. Это означает, что два
          файловых дескриптора совместно используют флаги (mq_flags).

       •  Потомок  наследует  копии  набора  потоков  открытых   каталогов   родителя   (смотрите
          opendir(3)).  В  POSIX.1  сказано,  что  соответствующие  потоки каталогов в родителе и
          потомке могут совместно использовать позицию в потоке каталога; в  Linux/glibc  они  не
          могут этого делать.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       On  success,  the PID of the child process is returned in the parent, and 0 is returned in
       the child.  On failure, -1 is returned in the parent, no child  process  is  created,  and
       errno is set to indicate the error.

ОШИБКИ

       EAGAIN Возникло  системного  ограничение  на количество нитей. Есть несколько ограничений,
              которые могут вызвать эту ошибку:

              •  RLIMIT_NPROC (задаётся с помощью setrlimit(2)), который ограничивает  количество
                 процессов и ните для реального ID пользователя;

              •  было  достигнуто  системное  ограничение  ядра  на количество процессов и нитей,
                 /proc/sys/kernel/threads-max (смотрите proc(5));

              •  достигнуто  максимальное  количество  PID,  /proc/sys/kernel/pid_max   (смотрите
                 proc(5)); или

              •  достигнуто  ограничение  на  PID  (pids.max),  наложенное контроллером cgroup на
                 «номер процесса» (PID).

       EAGAIN Вызывающий работает по алгоритму планирования SCHED_DEADLINE и у него не установлен
              флаг сброса-при-fork (reset-on-fork). Смотрите sched(7).

       ENOMEM Вызов  fork()  завершился  с  ошибкой  из-за  невозможности  разместить необходимые
              структуры ядра, потому что слишком мало памяти.

       ENOMEM Была попытка создания дочерний процесс в пространстве имён PID, чей процесс  «init»
              завершил работу. Смотрите pid_namespaces(7).

       ENOSYS Вызов  fork()  не  поддерживается  на  этой  платформе  (например,  из-за того, что
              аппаратное обеспечение не содержит блока управления памятью (MMU)).

       ERESTARTNOINTR (начиная с Linux 2.6.17)
              Системный вызов был прерван сигналом и перезапущен (может быть замечено только  при
              трассировке).

СТАНДАРТЫ

       POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

ЗАМЕЧАНИЯ

       В  Linux,  fork()  реализован  с  помощью «копирования страниц при записи» (copy-on-write,
       COW), поэтому расходы на вызов состоят из  времени  и  памяти,  требуемой  на  копирование
       страничных таблиц родителя и создания уникальной структуры, описывающей задачу.

   Отличия между библиотекой C и ядром
       Since glibc 2.3.3, rather than invoking the kernel's fork()  system call, the glibc fork()
       wrapper that is provided as part of the NPTL  threading  implementation  invokes  clone(2)
       with flags that provide the same effect as the traditional system call.  (A call to fork()
       is equivalent to a call to clone(2)  specifying flags as just SIGCHLD.)  The glibc wrapper
       invokes any fork handlers that have been established using pthread_atfork(3).

ПРИМЕРЫ

       See pipe(2)  and wait(2)  for more examples.

       #include <signal.h>
       #include <stdint.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>

       int
       main(void)
       {
           pid_t pid;

           if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
               perror("signal");
               exit(EXIT_FAILURE);
           }
           pid = fork();
           switch (pid) {
           case -1:
               perror("fork");
               exit(EXIT_FAILURE);
           case 0:
               puts("Child exiting.");
               exit(EXIT_SUCCESS);
           default:
               printf("Child is PID %jd\n", (intmax_t) pid);
               puts("Parent exiting.");
               exit(EXIT_SUCCESS);
           }
       }

СМ. ТАКЖЕ

       clone(2),  execve(2),  exit(2),  setrlimit(2),  unshare(2),  vfork(2), wait(2), daemon(3),
       pthread_atfork(3), capabilities(7), credentials(7)

ПЕРЕВОД

       Русский   перевод   этой    страницы    руководства    был    сделан    Azamat    Hackimov
       <azamat.hackimov@gmail.com>,   Dmitry   Bolkhovskikh  <d20052005@yandex.ru>,  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⟩.