Ответ
fork() — это системный вызов в Unix-подобных операционных системах (Linux, macOS, BSD), который создаёт новый процесс. Новый процесс (дочерний) является почти точной копией процесса, который его вызвал (родительский). Оба процесса продолжают выполнение со следующей инструкции после fork().
Ключевые характеристики:
- Копирование: Дочерний процесс получает копию адресного пространства (памяти), таблицы файловых дескрипторов и других атрибутов родителя.
- Различие PID: Дочерний процесс имеет уникальный идентификатор процесса (PID), отличный от родительского.
- Возвращаемое значение: Это основной способ отличить процессы:
- В родительском процессе
fork()возвращает PID дочернего процесса (положительное число). - В дочернем процессе
fork()возвращает 0. - В случае ошибки возвращается -1.
- В родительском процессе
Типичный паттерн использования в C:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork(); // Создаём новый процесс
if (pid == -1) {
perror("fork failed");
return 1;
}
if (pid > 0) {
// Код выполняется в РОДИТЕЛЬСКОМ процессе
printf("Parent: My PID is %d. Child's PID is %dn", getpid(), pid);
int status;
wait(&status); // Ожидаем завершения дочернего процесса
printf("Parent: Child process has finished.n");
} else {
// Код выполняется в ДОЧЕРНЕМ процессе (pid == 0)
printf("Child: My PID is %d. My parent's PID is %dn", getpid(), getppid());
// Здесь можно, например, выполнить другую программу с exec()
sleep(1); // Имитация работы
printf("Child: Exiting.n");
}
return 0;
}
Зачем это нужно в DevOps/администрировании?
- Демонизация: Демоны (фоновые службы) часто создаются через
fork(). Родительский процесс завершается, а дочерний продолжает работу под управлениемinit/systemd. - Параллелизм: Веб-серверы (например, Apache в prefork MPM) используют
fork()для создания пула процессов, каждый из которых обрабатывает отдельные HTTP-запросы. - Запуск внешних команд: Оболочка (bash) использует
fork()+exec()для запуска любой команды пользователя.