CLONE(2)

ИМЯ
clone - создать процесс-потомок

ОБЗОР
#include <sched.h>

int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);

_syscall2(int, clone, int, flags, void *, child_stack)

ОПИСАНИЕ
clone создаёт новый процесс как и fork(2). clone является библиотечной функцией верхнего уровня над системным вызовом clone, который далее будет называться sys_clone. Описание sys_clone даётся далее в конце данной страницы руководства. В отличие от fork(2), вышеуказанные системные вызовы позволяют процессу-потомку разделять части их контекста выполнения с вызывающим процессом: такие как область памяти, таблицу файловых дескрипторов и таблицу обработчиков сигналов. (Заметим, что на данной странице руководства, "вызывающий процесс" обычно соответствует "родительскому процессу". Но см. ниже описание CLONE_PARENT). Вызов clone в основном используется для реализации тредов (нитей): несколько тредов управления в какой-либо программе, которые запущены конкурентно в разделяемом пространстве памяти. Когда процесс-потомок создаётся с помощью clone, он запускает функциональное приложение fn(arg). (Это отличается от fork(2), где выполнение продолжается в потомке от точки вызова fork(2)). Аргумент fn является указателем на функцию, которая вызывается процессом-потомком в начале своего выполнения. Аргумент arg передаётся этой fn функции. Когда происходит возврат из функционального приложения fn(arg), процесс-потомок завершается. Целое значение, возвращаемое fn, является кодом выхода процесса-потомка. Процесс-потомок может также быть завершён явным образом, с помощью вызова exit(2) или после получения фатального сигнала. Аргумент child_stack задаёт положение стека, используемого процессом-потомком. Начиная с момента, когда процесс-потомок и вызывающий процесс могут разделять память, процесс-потомок не может выполняться в том же стеке, что и вызывающий процесс. Вызывающий процесс должен, таким образом, установить пространство памяти для стека процесса-потомка и передать указатель на это пространство в вызове clone. Стеки растут вниз для всех процессоров, на которых работает Linux (за исключением HP PA процессоров), так что child_stack обычно указывает на наиболее высокий адрес в пространстве памяти, которое устанавливается для стека процесса-потомка. Младший байт flags содержит номер сигнала, который посылается родителю, когда потомок умирает. Если этот сигнала задаётся как нечто отличное от SIGCHLD, то родительский процесс должен задать опцию __WALL или __WCLONE при ожидании завершения работы потомка с помощью вызова wait(2). Если никакой сигнал не задан, то родительский процесс не извещается сигналом, когда потомок завершается. Аргумент flags состоит из одного или более данных ниже битовых флагов, которые складываются по правилам битового сложения (OR). Флаги задают порядок процессов и то, что разделяется между вызывающим процессом и процессом-потомком:

CLONE_PARENT
    (ветка Linux 2.4 и выше) Если установлен флаг CLONE_PARENT, то родитель нового потомка (как возращает вызов getppid(2)) будет таким же как и у вызывающего процесса. Если флаг CLONE_PARENT не установлен, то (как и в fork(2)) родителем будет вызывающий процесс. Заметим, что это тот родительский процесс, который возращается вызовом getppid(2), и которому приходит сигнал, когда потомок завершается, так что если CLONE_PARENT установлен, то сигнал будет посылаться родителю вызывающего процесса, а не самому вызывающему процессу.

CLONE_FS
    Если флаг CLONE_FS установлен, вызывающий процесс и процесс-потомок разделяют одну и ту же информацию о фаловой системе. Она включает корневой каталог файловой системы, текущий рабочий каталог и значение umask. Любые вызовы chroot(2), chdir(2), или umask(2) выполняемые вызывающим процессом или процессом-потомком также дают взаимный эффект. Если флаг CLONE_FS не установлен, процесс-потомок работает с копией информации по файловой системе от вызывающего процесса, снятой на момент вызова clone. Вызовы chroot(2), chdir(2), umask(2) выполняемые позже одним из процессов не оказывают эффект на другой процесс.

CLONE_FILES
    Если флаг CLONE_FILES установлен, то вызывающий процесс и процесс-потомок разделяют одну и ту же таблицу файловых дескрипторов. Файловые дескрипторы всегда указывают на те же файлы в вызывающем процессе и процессе-потомке. Любые файловые дескрипторы, создаваемые вызывающим процессом или процессом-потомком также работают в другом процессе. Также, если один из процессов закрывает файловый дескриптор или изменяет ассоциированные с ним флаги, то это оказывает влияние и на другой процесс. Если флаг CLONE_FILES не установлен, процесс-потомок наследует копии всех файловых дескрипторов, открытых в вызывающем процессе на время вызова clone. Операции над файловыми дескрипторами, выполняемые позже вызывающим процессом или процессом-потомком, не оказывают эффекта на другой процесс.

CLONE_NEWNS
    (Начиная с Linux 2.4.19) Запускает потомок в новом пространстве имён. Каждый процесс живёт в некотором пространстве имён. Пространство имён процесса - это данные (список смонтированных файловых систем), описывающие файловую иерархию, видимую этим процессом. После вызова fork(2) или clone(2) где не установлен флаг CLONE_NEWNS, потомок живёт в том же пространстве имён, что и родитель. Системные вызовы mount(2) и umount(2) изменяют пространство имён вызывающего процесса и, с этого момента, оказывают эффект на все процессы, которые живут в этом же пространстве имён, но не оказывают эффект на процессы в других пространствах имён. После вызова clone(2) где флаг CLONE_NEWNS установлен, потомок запускается в новом пространстве имён, инициализированном копией пространства имён родителя. Только привелегированный процесс может устанавливать флаг CLONE_NEWNS. Не допускается совместное использование флагов CLONE_NEWNS и CLONE_FS в одном вызове clone.

CLONE_SIGHAND
    Если флаг CLONE_SIGHAND установлен, вызывающий процесс и процесс-потомок разделяют одну и ту же таблицу обработчиков сигналов. Если вызывающий процесс или процесс-потомок вызывают sigaction(2) для изменения поведения при получении сигнала, то это поведение изменяется также и в другом процессе. Однако, вызывающий процесс и процесс-потомок имеют различные маски сигналов и списки ожидающих обработки сигналов. Так, один из них может блокировать или деблокировать некоторые сигналы, используя sigprocmask(2) и это не будет оказывать эффект на другой процесс. Если флаг CLONE_SIGHAND не установлен, процесс-потомок наследует копию обработчиков событий вызывающего процесса, снятую на момент вызова clone . Вызовы sigaction(2) выполняемые после одним из процессов, не оказывают эффект на другой процесс.

CLONE_PTRACE
    Если флаг CLONE_PTRACE установлен и вызывающий процесс находится в режиме трассировки, то процесс-потомок таже будет работать в режиме трассировки (см. ptrace(2)).

CLONE_VFORK
    Если флаг CLONE_VFORK установлен, то выполнение вызывающего процесса приостанавливается пока потомок не освободит свои ресурсы виртуальной памяти через вызов execve(2) или _exit(2) (как в vfork(2)). Если флаг CLONE_VFORK не установлен, то после вызова и вызывающий процесс и процесс-потомок включаются в параллельную работу через системный планировщик и приложение не может знать в каком порядке будет осуществляться их выполнение.

CLONE_VM
    Если флаг CLONE_VM установлен, вызывающий процесс и процесс-потомок запускаются в том же пространстве памяти. В частности, записи в память, выполненные вызывающим процессом или процессом-потомком также видны из другого процесса. Кроме того, любые отражения памяти (mapping) или их завершение (unmapping) выполняемые через mmap(2) или munmap(2) потомком или вызывающим процессом, также оказывают эффект на другой процесс. Если флаг CLONE_VM не установлен, процесс потомок запускается в отдельной копии пространства памяти вызывающего процесса, снятой на момент вызова clone. Записи в память или отражения выполняемые одним процессом не дают эффекта в другом процессе как и в fork(2).

CLONE_PID
    Если флаг CLONE_PID установлен, процесс-потомок создаётся с таким же идентификатором процесса (ID) как и вызывающий процесс. Если CLONE_PID не установлен, процесс-потомок получает уникальный идентификатор процесса, отличающийся от идентификатора вызывающего процесса. Данный флаг может быть установлен только процессом загрузки системы (с PID 0).

CLONE_THREAD
    (Начиная с Linux 2.4) Если флаг CLONE_THREAD установлен, потомок размещается в той же группе тредов, что и вызывающий процесс. Если флаг CLONE_THREAD не устанлвен, то потомок размещается в своей собственной (новой) группе тредов, где ID группы такой же как и идентификатор процесса. (Группы тредов являются особенностью, добавленной в Linux 2.4 для поддержки класса тредов POSIX, списка тредов, разделяющих один и тот же PID. В Linux 2.4, вызов getpid(2) возвращает идентификатор группы тредов, вызывающего процесса.)

  sys_clone
Системный вызов sys_clone соответствует более закрытому fork(2) в том плане, что выполнение в потомке продолжается от места данного вызова. Таким образом sys_clone требует только аргументы flags и child_stack, которые имеют тот же смысл, что и для вызова clone. (Заметим, что порядок этих аргументов отличается от clone.) Другое отличие sys_clone состоит в том, что аргумент child_stack может быть нулём, в этом случае семантика copy-on-write обеспечивает получение потомком отдельных копий страниц стека, когда один из процессов изменяет стек. В этом случае, для правильной работы, не должен быть задан флаг CLONE_VM.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
В случае успеха, в вызывающий тред возращается PID процесса-потомка. В случае ошибки, в контекст вызываюего процесса возвращается -1, процесс потомок не будет создан и значение errno устанавливается соответствующим образом.

ОШИБКИ

EAGAIN
    Уже запущено слишком много процессов.

ENOMEM
    Не могу выделить требуемую память для структуры, описывающей процесс-потомок или для копирования тех частей контекста вызывающего процесса, которые необходимо скопировать.

EINVAL
    Возвращается clone когда для child_stack было задано нулевое значение.

EINVAL
    Оба флага CLONE_FS и CLONE_NEWNS были заданы в аргументе flags.

EINVAL
    CLONE_THREAD был задан, но CLONE_SIGHAND нет. (Начиная с Linux 2.5.35.)

EPERM
    CLONE_PID был задан процессом с ненулевым значением PID.

БАГИ
В версии ядра 2.1.97, флаг CLONE_PID не должен использоваться, так как другие части данного ядра и большинство системного программного обеспечения рассчитывают, что идентификаторы процессов являются уникальными. Вызов clone отсутствует в libc версии 5. libc 6 (известная как glibc 2) предоставляет вызов clone как описывается на данной странице руководства.

ЗАМЕЧАНИЯ
Для ядер версий 2.4.7-2.4.18 флаг CLONE_THREAD неявно подразумевает флаг CLONE_PARENT.

СООТВЕТСТВИЕ СТАНДАРТАМ
Вызовы clone и sys_clone являются специфичными для Linux и не должны использоваться в программах, которые задуманы как переносимые на другие платформы. Для программирования приложений, использующих треды (несколько тредов управления в одной и той же области памяти) лучше использовать библиотечную реализацию POSIX 1003.1c thread API, такую как библиотека LinuxThreads (включённая в glibc2). См. pthread_create(3). Данная страница руководства соответствует ядрам 2.0.x, 2.1.x, 2.2.x, 2.4.x, а также glibc 2.0.x и 2.1.x.

СМОТРИ ТАКЖЕ
fork(2), wait(2), pthread_create(3)

ПЕРЕВОД
Перевёл с английского Виктор Вислобоков <corochoone@perm.ru> 2004