Если указать флаг CLONE_PID, потомок будет иметь такой же идентификатор, как его родитель. В противном случае родитель и потомок получают разные идентификаторы PID (как в случае с fork() и vfork()). Этот флаг может устанавливать только процесс загрузки системы (тот, чей PID равен 0); он используется во время инициализации мультипроцессорных систем.
Флаг CLONE_PID не предназначен для применения в пользовательских приложениях. Он больше не доступен в Linux 2.6, а ему на замену пришел флаг CLONE_IDLETASK, который приводит к тому, что идентификатор нового процесса равняется 0. Флаг CLONE_IDLETASK доступен только для внутреннего применения в ядре и игнорируется вызовом clone(). Он используется для создания невидимых процессов, находящихся в режиме ожидания; каждый такой процесс отводится для отдельного ЦПУ (в многопроцессорных системах их может быть несколько).
Трассировка процессов: CLONE_PTRACE и CLONE_UNTRACED
Если указать флаг CLONE_PTRACE, потомок трассируемого процесса тоже будет трассироваться. Подробности о трассировке процессов (которая используется при отладке и в команде strace) ищите на справочной странице ptrace(2).
В версиях Linux 2.6 и выше можно указывать флаг CLONE_UNTRACED, который не позволяет трассируемому процессу применить флаг CLONE_PTRACE к своему потомку. Он используется внутри системы для создания потоков ядра.
Приостановка родителя до тех пор, пока потомок не завершится или не выполнит exec: CLONE_VFORK
Если указать флаг CLONE_VFORK, выполнение родителя приостанавливается до тех пор, пока потомок не освободит ресурсы своей виртуальной памяти с помощью вызовов exec() или _exit() (как в случае с vfork()).
Новые флаги вызова clone() для поддержки контейнеров
В Linux 2.6.19 и выше появилась поддержка целого ряда новых флагов для вызова clone(): CLONE_IO, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWPID, CLONE_NEWUSER и CLONE_NEWUTS (см. справочную страницу clone(2)).
Большинство из этих флагов обеспечивают поддержку
Для реализации контейнеров разработчикам Linux пришлось создать в ядре виртуальный слой вокруг каждого глобального ресурса системы — это, например, касается идентификаторов процессов, сетевого стека, идентификаторов, возвращаемых вызовом uname(), IPC-объектов из System V, а также пространств имен для идентификаторов пользователей и групп. Благодаря этому каждый контейнер может получить собственный экземпляр этих ресурсов.
Контейнеры имеют множество различных применений, включая следующие:
• контроль над выделением ресурсов системы, таких как пропускная способность сети или процессорное время (например, одному контейнеру можно выдать 75 % процессорного времени, а другому — 25 %);
• предоставление нескольких легковесных виртуальных серверов на одном и том же компьютере;
• замораживание контейнера, чтобы приостановить выполнение всех процессов внутри него и позже, возможно после миграции на другой компьютер, запустить их заново;
• возможность сбросить на диск состояние приложения (создав тем самым контрольную точку) и затем восстановить его (возможно, после аварийного завершения программы или плановой/неплановой перезагрузки системы), чтобы продолжить выполнение с того самого места.
Использование флагов вызова clone()
Вызов fork(), грубо говоря, соответствует вызову clone(), аргумент flags которого равен SIGCHLD, тогда как vfork() соответствует clone() со следующими флагами:
CLONE_VM | CLONE_VFORK | SIGCHLD
Обертка fork() библиотеки glibc версии 2.3.3 и выше, которая входит в состав реализации NPTL-потоков, обходит одноименный системный вызов и обращается вместо него к вызову clone(). Эта функция запускает любые обработчики, установленные вызывающим процессом с помощью pthread_atfork() (см. раздел 33.3).
В библиотеке LinuxThreads для создания потоков вызов clone() (но только с первыми четырьмя его аргументами) применяется в сочетании со следующими флагами:
CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND
В библиотеке NPTL вызов clone() (вместе со всеми семью его аргументами) создает потоки с помощью таких флагов:
CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND | CLONE_THREAD | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
28.2.2. Расширения к вызову waitpid() для клонированных потомков