ИМЯ¶
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