int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
_syscall2(int, clone, int, flags, void *, child_stack)
В отличие от 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 не установлен, то (как и в fork(2)) родителем будет вызывающий процесс.
Заметим, что это тот родительский процесс, который возращается вызовом getppid(2), и которому приходит сигнал, когда потомок завершается, так что если CLONE_PARENT установлен, то сигнал будет посылаться родителю вызывающего процесса, а не самому вызывающему процессу.
Если флаг CLONE_FS не установлен, процесс-потомок работает с копией информации по файловой системе от вызывающего процесса, снятой на момент вызова clone. Вызовы chroot(2), chdir(2), umask(2) выполняемые позже одним из процессов не оказывают эффект на другой процесс.
Если флаг CLONE_FILES не установлен, процесс-потомок наследует копии всех файловых дескрипторов, открытых в вызывающем процессе на время вызова clone. Операции над файловыми дескрипторами, выполняемые позже вызывающим процессом или процессом-потомком, не оказывают эффекта на другой процесс.
Каждый процесс живёт в некотором пространстве имён. Пространство имён процесса - это данные (список смонтированных файловых систем), описывающие файловую иерархию, видимую этим процессом. После вызова fork(2) или clone(2) где не установлен флаг CLONE_NEWNS, потомок живёт в том же пространстве имён, что и родитель. Системные вызовы mount(2) и umount(2) изменяют пространство имён вызывающего процесса и, с этого момента, оказывают эффект на все процессы, которые живут в этом же пространстве имён, но не оказывают эффект на процессы в других пространствах имён.
После вызова clone(2) где флаг CLONE_NEWNS установлен, потомок запускается в новом пространстве имён, инициализированном копией пространства имён родителя.
Только привелегированный процесс может устанавливать флаг CLONE_NEWNS. Не допускается совместное использование флагов CLONE_NEWNS и CLONE_FS в одном вызове clone.
Если флаг CLONE_SIGHAND не установлен, процесс-потомок наследует копию обработчиков событий вызывающего процесса, снятую на момент вызова clone . Вызовы sigaction(2) выполняемые после одним из процессов, не оказывают эффект на другой процесс.
Если флаг CLONE_VFORK не установлен, то после вызова и вызывающий процесс и процесс-потомок включаются в параллельную работу через системный планировщик и приложение не может знать в каком порядке будет осуществляться их выполнение.
Если флаг CLONE_VM не установлен, процесс потомок запускается в отдельной копии пространства памяти вызывающего процесса, снятой на момент вызова clone. Записи в память или отражения выполняемые одним процессом не дают эффекта в другом процессе как и в fork(2).
Если CLONE_PID не установлен, процесс-потомок получает уникальный идентификатор процесса, отличающийся от идентификатора вызывающего процесса.
Данный флаг может быть установлен только процессом загрузки системы (с PID 0).
Если флаг CLONE_THREAD не устанлвен, то потомок размещается в своей собственной (новой) группе тредов, где ID группы такой же как и идентификатор процесса.
(Группы тредов являются особенностью, добавленной в Linux 2.4 для поддержки класса тредов POSIX, списка тредов, разделяющих один и тот же PID. В Linux 2.4, вызов getpid(2) возвращает идентификатор группы тредов, вызывающего процесса.)
Другое отличие sys_clone состоит в том, что аргумент child_stack может быть нулём, в этом случае семантика copy-on-write обеспечивает получение потомком отдельных копий страниц стека, когда один из процессов изменяет стек. В этом случае, для правильной работы, не должен быть задан флаг CLONE_VM.
В версии ядра 2.1.97, флаг CLONE_PID не должен использоваться, так как другие части данного ядра и большинство системного программного обеспечения рассчитывают, что идентификаторы процессов являются уникальными.
Вызов clone отсутствует в libc версии 5. libc 6 (известная как glibc 2) предоставляет вызов clone как описывается на данной странице руководства.
Данная страница руководства соответствует ядрам 2.0.x, 2.1.x, 2.2.x, 2.4.x, а также glibc 2.0.x и 2.1.x.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |