Что такое форк (fork) процесса в Linux?

«Что такое форк (fork) процесса в Linux?» — вопрос из категории Linux, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Fork (вилочное разветвление) — это системный вызов в ядре Linux (fork()), который создаёт новый процесс (дочерний) путём полного дублирования текущего процесса (родительского). Это основной способ создания процессов в Unix-подобных системах.

Что происходит при вызове fork():

  1. Ядро создаёт почти точную копию родительского процесса: копирует сегменты памяти (стек, куча, данные, текст), таблицу файловых дескрипторов, контекст выполнения.
  2. Новому процессу присваивается уникальный PID (Process ID).
  3. В родительский процесс возвращается PID дочернего процесса.
  4. В дочерний процесс возвращается 0. Это ключевой момент для различения процессов в коде.
  5. Оба процесса продолжают выполнение со следующей инструкции после fork().

Типичный паттерн: Fork + Exec Дочерний процесс редко выполняет тот же код, что и родитель. Обычно он сразу вызывает семейство системных вызовов exec() (например, execve()), которое заменяет образ памяти дочернего процесса на новый исполняемый файл (например, /bin/ls).

Пример на 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("Child: My PID is %d, Parent PID is %dn", getpid(), getppid());
        // Заменяем себя программой 'ls'
        execlp("ls", "ls", "-la", NULL);
        // Если execlp вернул управление — значит, ошибка
        perror("execlp failed");
        return 1;
    } else {
        // Этот код выполняется ТОЛЬКО в родительском процессе
        printf("Parent: My PID is %d, Child PID is %dn", getpid(), pid);
        int status;
        wait(&status); // Ожидаем завершения дочернего процесса
        printf("Child exited with status %dn", WEXITSTATUS(status));
    }
    return 0;
}

Значение для DevOps/системного администрирования:

  • Так работают демоны и серверные процессы (например, nginx master процесс форкает worker процессы).
  • Понимание форка необходимо для отладки, анализа потребления памяти (Copy-On-Write механизм) и написания скриптов, управляющих процессами.
  • Неконтролируемое создание процессов через форк может привести к "fork bomb" — атаке типа "отказ в обслуживании".