fork()

Создать новый процесс

Прототип:

#include <sys/types.h>
#include <process.h>
pid_t fork( void );

Библиотека:

libc

Описание:

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

Можно использовать pthread_atfork() для регистрации обработчика функции fork(), который будет вызван перед или после вызова fork().

POSIX требует, чтобы дочерний процесс использовал только функции, безопасные для асинхронных сигналов, до того, как будет вызвана одна из функций exec*(). Если программа использует мьютексы, вероятно, понадобится использовать обработчик pthread_atfork(), который заблокирует все мьютексы перед fork().


Caution: При использовании функции fork() ряд сущностей, создающих внутренний мьютекс в момент инициализации, в только что созданном процессе будут иметь неопределенное состояние и их дальнейшее использование крайне не рекомендуется. К ним относятся thread_pool_*(), resmgr_*() (включая обработчики сообщений) и dispatch_*().

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


Начиная с ЗОСРВ «Нейтрино» редакции 2020 библиотека libc предоставляет возможность использовать fork() в многопоточных процессах

Возвращаемое значение:

Нулевое значение для дочернего процесса; идентификатор дочернего процесса для родительского процесса. Оба процесса продолжают выполнение от функции fork(). Если возникла ошибка, fork() возвращает -1 родительскому процессу и устанавливает errno.

Коды ошибок:

EAGAIN
Недостаточно ресурсов для создания дочернего процесса. Например, было превышено максимальное число разрешенных процессов; смотрите ресурс RLIMIT_NPROC для getrlimit().
ENOMEM
Процесс требует больше ппамяти, чем система может предоставить.
ENOSYS
Функция fork() не реализована для данной модели сохранения памяти.

Примеры:

/*
* This program executes the program and arguments
* specified by argv[1..argc]. The standard input
* of the executed program is converted to upper
* case.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <process.h>
#include <sys/wait.h>
int main( int argc, char **argv )
{
pid_t pid;
pid_t wpid;
int fd[2];
char buffer[80];
int i, len;
int status;
if ( pipe( fd ) == -1 )
{
perror( "pipe" );
return (EXIT_FAILURE);
}
if ( ( pid = fork() ) == -1 )
{
perror( "fork" );
return (EXIT_FAILURE);
}
if ( pid == 0 )
{
/* This is the child process. Move read end of the pipe to stdin ( 0 ),
* close any extraneous file descriptors, then use exec to 'become' the command. */
dup2( fd[0], 0 );
close( fd[1] );
execvp( argv[1], argv + 1 );
/* This can only happen if exec fails; print message and exit. */
perror( argv[1] );
return (EXIT_FAILURE);
} else {
/* This is the parent process. Remove extraneous file descriptors, read
* descriptor 0, write into pipe, close pipe and wait for child to die. */
close( fd[0] );
while ( ( len = read( 0, buffer, sizeof( buffer ) ) ) > 0 )
{
for ( i = 0; i < len; i++ )
{
if ( isupper( buffer[i] ) )
buffer[i] = tolower( buffer[i] );
}
write( fd[1], buffer, len );
}
close( fd[1] );
do {
wpid = waitpid( pid, &status, 0 );
} while( WIFEXITED( status ) == 0 );
return (WEXITSTATUS( status ));
}
}

Классификация:

POSIX 1003.1

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

pthread_atfork(), errno, execl(), execle(), execlp(), execlpe(), execv(), execve(), execvp(), execvpe(), spawn(), spawnl(), spawnle(), spawnlp(), spawnlpe(), spawnp(), spawnv(), spawnve(), spawnvp(), spawnvpe(), wait()




Предыдущий раздел: Описание API системной библиотеки