Provided by: manpages-de-dev_4.21.0-2_all 

BEZEICHNUNG
clone, __clone2, clone3 - erzeugt einen Kindprozess
BIBLIOTHEK
Standard-C-Bibliothek (libc, -lc)
ÜBERSICHT
/* Prototyp für die Glibc-Wrapper-Funktion */
#define _GNU_SOURCE
#include <sched.h>
int clone(int (*fn)(void *_Nullable), void *Stapel, int Schalter,
void *_Nullable Arg, ... /* pid_t *_Nullable Eltern_tid,
void *_Nullable tls,
pid_t *_Nullable Kind_tid */ );
/* Für den Prototyp des rohen clone()-Systemaufrufs siehe ANMERKUNGEN */
#include <linux/sched.h> /* Definition von struct clone_args */
#include <sched.h> /* Definition der CLONE_*-Konstanten */
#include <sys/syscall.h> /* Definition der SYS_*-Konstanten */
#include <unistd.h>
long syscall(SYS_clone3, struct clone_args *cl_args, size_t groesse);
Hinweis: Glibc stellt keinen Wrapper für clone3() bereit; rufen Sie ihn mittels syscall(2) auf.
BESCHREIBUNG
Diese Systemaufrufe erzeugen auf eine ähnliche Weise wie fork(2) einen neuen Prozess (»Kind«).
Im Gegensatz zu fork(2) bieten diese Systemaufrufe eine genauere Kontrolle darüber, welche Teile des
Ausführungskontextes vom aufrufenden und vom Kindprozess gemeinsam benutzt werden. Beispielsweise kann
der Aufrufende mittels dieser Systemaufrufe steuern, ob die zwei Prozesse den virtuellen Adressraum, die
Tabelle der Dateideskriptoren und die Tabelle der Signal-Handler gemeinsam benutzen. Diese Systemaufrufe
ermöglichen es auch, den neuen Kindprozess in einen separaten Namensraum (siehe namespaces(7)) abzulegen.
Beachten Sie, dass in dieser Handbuchseite der »aufrufende Prozess« normalerweise der »Elternprozess«
ist. Siehe aber auch die nachfolgende Beschreibung von CLONE_PARENT und CLONE_THREAD.
Diese Seite beschreibt die folgenden Schnittstellen:
• Die clone()-Wrapper-Funktion von Glibc als auch den darunterliegenden Systemaufruf, auf dem sie
basiert. Der Haupttext erklärt die Wrapper-Funktion. Die Unterschiede zum rohen Systemaufruf werden
gegen Ende dieser Seite erläutert.
• Der neuere Systemaufruf clone3().
Im Rest der Seite wird die Terminologie »der Clone-Aufruf« verwandt, wenn Details erklärt werden, die auf
alle diese Schnittstellen zutreffen.
Die clone()-Wrapper-Funktion
Wird mit der clone()-Wrapper-Funktion ein Kindprozess erzeugt, beginnt es die Ausführung durch Aufruf der
Funktion, auf die das Argument fn zeigt. (Dies ist ein Unterschied zu fork(2), wo die Ausführung im
Kindprozess vom Punkt des fork(2)-Aufrufs fortfährt.) Das Argument arg wird als Argument der Funktion fn
übergeben.
Kehrt die Funktion fn(arg) zurück, so beendet sich der Kindprozess. Der Ganzzahlwert, der von fn
zurückgeliefert wird, entspricht dem Exit-Status des Kindprozesses. Der Kindprozess kann auch durch den
expliziten Aufruf von exit(2) oder durch den Empfang eines fatalen Signals beendet werden.
Das Argument Stapel bestimmt den Ort des Stapelspeichers, der vom Kindprozess verwendet wird. Da der
aufrufende und der Kindprozess sich Speicherbereiche teilen können, kann der Kindprozess nicht auf dem
selben Stapelspeicher wie der aufrufende Prozess laufen. Der aufrufende Prozess muss daher einen
Speicherbereich als Stapelspeicher für den Kindprozess bereithalten und per clone einen Zeiger darauf an
den Kindprozess übergeben. Der Stapelspeicher wächst (mit Ausnahme der PA-Prozessoren von HP) auf allen
von Linux unterstützten Prozessoren nach unten, so dass Stapel für gewöhnlich auf die oberste Adresse im
bereitgehaltenen Speicherbereich zeigt. Beachten Sie, dass clone() keine Möglichkeit bereitstellt, mit
der der Aufrufende den Kernel über die Größe des Stapel-Bereichs informieren könnte.
Die verbliebenen Argumente für clone() werden unten behandelt.
clone3()
Der Systemaufruf clone3() stellt eine Obermenge der Funktionalität der älteren Schnittstelle clone()
bereit. Er stellt auch eine Reihe von API-Verbesserungen bereit, einschließlich: Platz für zusätzliche
Schalter-Bits; deutlichere Trennung beim Einsatz der verschiedenen Argumente, die Möglichkeit, die Größe
des Stapel-Bereichs des Kindprozesses festzulegen.
Wie bei fork(2) kehrt clone3() sowohl im Eltern- als auch im Kindprozess zurück. Er liefert 0 im
Kindprozess und die PID des Kindprozesses im Elternprozess zurück.
Das Argument cl_args von clone3() ist eine Struktur der folgenden Form:
struct clone_args {
u64 flags; /* Schalter-Bit-Maske */
u64 pidfd; /* Wo der PID-Dateideskriptor gespeichert
werden soll (int *) */
u64 child_tid; /* Wo die Kind-TID gespeichert werden soll,
im Speicher des Kindes (pid_t *) */
u64 parent_tid; /* Wo die Kind-TID gespeichert werden soll,
im Speicher des Elternprozesses (pid_t *) */
u64 exit_signal; /* Beim Beenden des Kindprozesses an den Elternprozess
zu sendendes Signal */
u64 stack; /* Zeiger auf das niedrigste Byte des Stapels */
u64 stack_size; /* Größe des Stapels */
u64 tls; /* Ort eines neuen TLS */
u64 set_tid; /* Zeiger auf ein pid_t-Feld
(seit Linux 5.5) */
u64 set_tid_size; /* Anzahl von Elementen in set_tid
(seit Linux 5.5) */
u64 cgroup; /* Dateideskriptor für Ziel-Cgroup
eines Kindes (seit Linux 5.7) */
};
Das an clone3() übergebene Argument groesse sollte auf die Größe dieser Struktur initialisiert werden.
(Die Existenz des Arguments groesse ermöglicht zukünftige Erweiterungen der clone_args-Struktur.)
Der Stapel für den Kindprozess wird in cl_args.stack, der auf das niedrigste Byte des Stapel-Bereichs
zeigt, und cl_args.stack_size, der die Größe des Stapel-Bereichs in Byte festlegt, angegeben. Falls der
Schalter CLONE_VM (siehe unten) angegeben ist, muss ein Stapel explizit reserviert und festgelegt werden.
Andernfalls können diese Felder als NULL und 0 angegeben werden, wodurch der Kindprozess den gleichen
Stapel-Bereich wie der Elternprozess verwendet (im eigenen virtuellen Adressraum des Kindprozesses).
Die verbliebenen Felder im Argument cl_args werden unten behandelt.
Äquivalenz zwischen den Argumenten von clone() und clone3()
Anders als die ältere clone()-Schnittstelle, bei der die Argumente individuell übergeben werden, werden
die Argumente bei der neueren clone3()-Schnittstelle in die oben gezeigte Struktur clone_args gepackt.
Diese Struktur erlaubt es, dass eine Obermenge an Informationen über die clone()-Argumente übergeben
wird.
Die folgende Tabelle zeigt die Äquivalenz zwischen den Argumenten von clone() und den Feldern in den an
clone3() übergebenen clone_args:
clone() clone3() Hinweise
Feld cl_args
Schalter & ~0xff flags Für die meisten Schalter;
Details unten
parent_tid pidfd Siehe CLONE_PIDFD
child_tid child_tid Siehe CLONE_CHILD_SETTID
parent_tid parent_tid Siehe CLONE_PARENT_SETTID
Schalter & 0xff exit_signal
Stapel Stapel
--- stack_size
tls tls Siehe CLONE_SETTLS
--- set_tid Siehe weiter unten für Details.
--- set_tid_size
--- cgroup Siehe CLONE_INTO_CGROUP
Das Kind-Beendigungssignal
Wenn sich der Kindprozess beendet, kann ein Signal an den Elternprozess gesandt werden. Das
Beendigungssignal wird in den niedrigen Bytes von Schalter (clone()) oder in cl_args.exit_signal
(clone3()) angegeben. Falls dieses Signal als etwas anderes als SIGCHLD angegeben wurde, dann muss der
Elternprozess die Optionen __WALL oder __WCLONE angeben, wenn er mit wait(2) auf den Kindprozess wartet.
Falls kein Signal (d.h. Null) angegeben wurde, wird dem Elternprozess nicht signalisiert, wenn der
Kindprozess endet.
Das Feld set_tid
Standardmäßig wählt der Kernel die nächste sequenzielle PID für den neuen Prozess in jedem der
PID-Namensräume, in denen er vorhanden ist. Beim Erstellen eines Prozesses mit clone3() kann das (seit
Linux 5.5 verfügbare) Feld set_tid zur Auswahl bestimmter PIDs für den Prozess in einem oder allen der
PID-Namensräume, in denen er vorhanden ist, eingesetzt werden. Falls die PID des neu erstellten Prozesses
nur im aktuellen PID-Namensraum oder in dem neu erstellten PID-Namensraum (falls Schalter CLONE_NEWPID
enthält) gesetzt werden soll, dann muss das erste Element in dem Feld set_tid auf die gewünschte PID
gesetzt werden und set_tid_size muss 1 sein.
Falls die PID des neu erstellten Prozesses einen bestimmten Wert in mehreren PID-Namensräumen haben soll,
dann kann dass Feld set_tid über mehrere Einträge verfügen. Der erste Eintrag definiert die PID im am
tiefsten verschachtelten PID-Namensraum und jeder der nachfolgenden Einträge enthält die PID in dem
entsprechenden Vorfahren-PID-Namensraum. Die Anzahl der PID-Namensräume in denen eine PID gesetzt werden
soll, wird mit set_tid_size gesetzt; dieser Wert kann nicht größer als die Anzahl der derzeit
verschachtelten PID-Namensräume sein.
Um einen Prozess zu erzeugen, der die nachfolgenden PIDs in einem PID-Namensraum hat:
PID-NS-Stufe Angeforderte PID Hinweise
0 31496 Äußerster PID-Namensraum
1 42
2 7 Innerster PID-Namensraum
Setzen Sie das Feld auf:
set_tid[0] = 7;
set_tid[1] = 42;
set_tid[2] = 31496;
set_tid_size = 3;
Falls nur die PIDs in den zwei innersten PID-Namensräumen festgelegt werden müssen, setzen Sie das Feld
auf:
set_tid[0] = 7;
set_tid[1] = 42;
set_tid_size = 2;
Die PID in den PID-Namensräumen außerhalb der zwei innersten PID-Namensräume ist genauso wie jede andere
PID ausgewählt.
Die Funktionalität set_tid benötigt CAP_SYS_ADMIN oder (seit Linux 5.9) CAP_CHECKPOINT_RESTORE in allen
Benutzernamensräumen, die dem des Ziel-PID-Namensraumes gehören.
Aufrufende dürfen in einem gegebenen PID-Namensraum nur eine PID größer als 1 auswählen, falls ein
init-Prozess (d.h. ein Prozess mit der PID 1) in diesem Namensraum bereits existiert. Andernfalls muss
der PID-Eintrag für diesen PID-Namensraum 1 sein.
Die Schaltermaske
Sowohl clone() als auch clone3() erlauben eine Schalter-Bit-Maske, die das Verhalten verändert und dem
Aufrufenden festzulegen erlaubt, was von dem aufrufenden Prozess und dem Kindprozess gemeinsam benutzt
wird. Diese Bitmaske—das Argument Schalter von clone() oder das an clone3() übergebene Feld
cl_args.flags—wird im Rest dieser Handbuchseite als die Schalter-Maske bezeichnet.
Die Schalter-Maske wird als bitweises ODER von Null oder mehreren der oben aufgeführten Konstanten
angegeben. Falls nicht unten anders angegeben, sind diese Schalter sowohl in clone() als auch clone3()
verfügbar (und haben die gleiche Wirkung).
CLONE_CHILD_CLEARTID (seit Linux 2.5.49)
Die Kind-Thread-Kennung an der durch Kind_tid gezeigten Stelle (clone()) oder cl_args.child_tid
(clone3()) im Kindspeicher bereinigen (nullen), wenn das Kind sich beendet und beim Futex (»fast
userspace mutual exclusion«/schneller gegenseitiger Ausschluss im Userspace) an dieser Adresse
aufwachen lassen. Die betroffene Adresse könnte durch den Systemaufruf set_tid_address(2) geändert
werden. Dies wird von Threading-Bibliotheken benutzt.
CLONE_CHILD_SETTID (seit Linux 2.5.49)
Speichert die Kind-Thread-Kennung an der Stelle, auf die Kind_tid (clone()) oder cl_args.child_tid
(clone3()) zeigt, im Kindspeicher. Die Speicheraktion wird abgeschlossen, bevor der Clone-Aufruf
die Steuerung an den Benutzerraum im Kindprozess zurückgibt. (Beachten Sie, dass die
Speicheraktion noch nicht abgeschlossen sein könnte, bevor der Clone-Aufruf den Elternprozess
zurückliefert, was relevant ist, wenn auch der Schalter CLONE_VM eingesetzt wird.)
CLONE_CLEAR_SIGHAND (seit Linux 5.5)
Standardmäßig sind die Signal-Zuordnungen im Kind-Thread identisch zu denen im Eltern-Prozess.
Falls dieser Schalter angegeben ist, dann werden alle Signale, die im Eltern-Prozess gehandhabt
werden, im Kind-Thread auf ihre Standardzuordnung (SIG_DFL) zurückgesetzt.
Es ergibt keinen Sinn, diesen Schalter zusammen mit CLONE_SIGHAND anzugeben; daher ist diese
Kombination nicht erlaubt.
CLONE_DETACHED (historisch)
Eine Zeit lang (während der Linux-2.5-Entwicklungsserie) gab es einen Schalter CLONE_DETACHED, der
dazu führte, dass der Elternprozess kein Signal empfing, wenn sich das Kind beendete. Schließlich
wurde die Auswirkung dieses Schalters in dem Schalter CLONE_THREAD mit aufgenommen und zum
Zeitpunkt der Veröffentlichung von Linux 2.6.0 hatte dieser Schalter keine Auswirkung. Beginnend
mit Linux 2.6.2 verschwand die Notwendigkeit, diesen Schalter mit CLONE_THREAD zusammen anzugeben.
Dieser Schalter ist noch definiert, wird aber beim Aufruf von clone() normalerweise ignoriert.
Siehe allerdings die Beschreibung von CLONE_PIDFD für einige Ausnahmen.
CLONE_FILES (since Linux 2.0)
Ist CLONE_FILES gesetzt, teilen sich der aufrufende und der Kindprozess ihre
Dateideskriptor-Tabellen. Jeder Dateideskriptor, der im aufrufenden Prozess oder vom Kindprozess
erzeugt wird, ist auch im anderen Prozess gültig. Ebenso wirkt sich das Schließen eines
Dateideskriptors oder das Ändern der zugehörigen Schalter (benutzen der F_SETFD-Operation von
fcntl(2)) auf den anderen Prozess aus. Falls sich ein Prozess eine Dateideskriptor-Tabelle teilt
und execve(2) aufruft, wird seine Dateideskriptor-Tabelle dupliziert (nicht länger geteilt).
Ist CLONE_FILES nicht gesetzt, erbt der Kindprozess zur Ausführungszeit von Clone eine Kopie der
aktuell geöffneten Dateideskriptoren. Anschließende Aktionen, die Dateideskriptoren öffnen oder
schließen bzw. deren Schalter ändern, werden entweder vom aufrufenden Prozess oder dem Kindprozess
durchgeführt und betreffen nicht den jeweils anderen Prozess. Beachten Sie aber, dass sich die
duplizierten Dateideskriptoren im Kind auf die gleiche offene Dateideskription wie der
korrespondierende Dateideskriptor im aufrufenden Prozess bezieht und sich daher den Dateiversatz
und die Dateistatusschalter mit diesem teilt (siehe open(2)).
CLONE_FS (seit Linux 2.0)
Ist CLONE_FS gesetzt, teilen sich aufrufender Prozess und Kindprozess ihre Informationen über das
Dateisystem. Dazu zählen der Ort des Wurzelverzeichnisses, das aktuelle Arbeitsverzeichnis und die
Maske der Dateizugriffsrechte (umask). Jeder Aufruf von chroot(2), chdir(2) oder umask(2),
entweder durch den aufrufenden Prozess oder den Kindprozess, beeinflusst auch den jeweils anderen
Prozess.
Ist CLONE_FS nicht gesetzt, arbeitet der Kindprozess mit einer Kopie der Dateisysteminformationen
des aufrufenden Prozesses zur Zeit des Clone-Aufrufs. Spätere Aufrufe von chroot(2), chdir(2) oder
umask(2) beeinflussen den anderen Prozess nicht.
CLONE_INTO_CGROUP (seit Linux 5.7)
Standardmäßig wird ein Kindprozess in die gleiche Version-2-Cgroup wie sein Elternprozess
abgelegt. Der Schalter CLONE_INTO_CGROUP ermöglicht es, den Kindprozess in einer anderen
Version-2-Cgroup zu erstellen. (Beachten Sie, dass CLONE_INTO_CGROUP nur für Version-2-Cgroups
wirksam wird.)
Um den Kindprozess in eine andere Cgroup abzulegen, legt der Aufrufende CLONE_INTO_CGROUP in
cl_args.flags fest und übergibt im Feld cl_args.cgroup einen Dateideskriptor, der sich auf eine
Version-2-Cgroup bezieht. (Dieser Dateideskriptor kann erhalten werden, indem ein
Cgroup-v2-Verzeichnis mittels des Schalters O_RDONLY oder O_PATH geöffnet wird.) Beachten Sie,
dass sämtliche übliche Einschränkungen (beschrieben in cgroups(7)) über das Ablegen eines
Prozesses in einer Version-2-Cgroup gültig bleiben.
Folgende Anwendungsfälle für CLONE_INTO_CGROUP sind unter anderen möglich:
• Das Erzeugen eines Prozesses in einer Cgroup, die sich von der des Elternprozesses
unterscheidet, ermöglicht es einem Diensteverwalter, neue Dienste direkt in dedizierte Cgroups
zu erzeugen. Dies beseitigt das Flackern bei der Buchführung, das erzeugt würde, falls der
Kindprozess erst in der gleichen Cgroup wie der Elternprozess erzeugt und dann in die
Ziel-Cgroup verschoben würde. Desweiteren ist die Erzeugung des Kindprozesses direkt in der
Ziel-Cgroup deutlich billiger als das Verschieben des Kindprozesses in die Ziel-Cgroup, nachdem
er erstellt wurde.
• Der Schalter CLONE_INTO_CGROUP erlaubt auch die Erstellung eingefrorener Kindprozesse durch
Erzeugung dieser in einer eingefrorenen Cgroup. (Siehe cgroups(7) für eine Beschreibung des
Einfrier-Controllers.)
• Für Anwendungen mit Threads (oder sogar Thread-Implementierungen, die Cgroups verwenden, um
einzelne Threads zu begrenzen) ist es möglich, ein festes Cgroup-Layout zu errichten, bevor
jeder Thread direkt in seine Ziel-Cgroup erzeugt wird.
CLONE_IO (seit Linux 2.6.25)
Ist CLONE_FS gesetzt, teilt sich der neue Prozess einen E/A-Kontext mit dem aufrufenden Prozess.
Falls dieser Schalter nicht gesetzt ist (wie bei fork(2)), hat der neue Prozess seinen eigenen
E/A-Kontext.
Der E/A-Kontext entspricht dem E/A-Gültigkeitsbereich des Platten-Schedulers, d.h. welches der
E/A-Scheduler zur Modellplanung für E/As des Prozesses benutzt. Falls sich Prozesse den gleichen
E/A-Kontext teilen, werden sie vom E/A-Scheduler als ein einziger betrachtet. Als Konsequenz
daraus müssen sie sich die gleiche Plattenzeitzugriffzeit teilen. Einige E/A-Scheduler ermöglichen
zwei Prozessen, die einen E/A-Kontext teilen, ihren Plattenzugriff zu verzahnen. Falls mehrere
Prozesse E/A im Auftrag des gleichen Prozesses durchführen (aio_read(3) zum Beispiel), sollten sie
für eine bessere E/A-Leistung CLONE_IO verwenden.
Falls der Kernel nicht mit der Option CONFIG_BLOCK konfiguriert wurde, bewirkt dieser Schalter
nichts.
CLONE_NEWCGROUP (seit Linux 4.6)
Der Prozess wird in einem neuen cgroup-Namensraum erstellt. Falls dieser Schalter nicht gesetzt
ist, dann wird der Prozess (wie mit fork(2)) im gleichen cgroup-Namensraum wie der aufrufende
Prozess erstellt.
Weitere Informationen über cgroup-Namensräume finden Sie unter cgroup_namespaces(7).
Nur ein privilegierter Prozess (CAP_SYS_ADMIN) kann CLONE_NEWCGROUP angeben.
CLONE_NEWIPC (seit Linux 2.6.19)
Wenn CLONE_NEWIPC gesetzt ist, dann wird der Prozess in einem neuen IPC-Namensraum erstellt. Falls
dieser Schalter nicht gesetzt ist, dann wird der Prozess (wie mit fork(2)) im gleichen
IPC-Namensraum wie der aufrufende Prozess erstellt.
Weitere Informationen zu IPC-Namensräumen finden Sie in ipc_namespaces(7).
Nur ein privilegierter Prozess (CAP_SYS_ADMIN) kann CLONE_NEWIPC angeben. Dieser Schalter darf
nicht zusammen mit CLONE_SYSVSEM angegeben werden.
CLONE_NEWNET (seit Linux 2.6.24)
(Die Implementierung dieses Schalters wurde erst ungefähr mit der Linux-Version 2.6.29
abgeschlossen.)
Wenn CLONE_NEWNET gesetzt ist, dann wird der Prozess in einem neuen Netzwerk-Namensraum erstellt.
Falls dieser Schalter nicht gesetzt ist, dann wird der Prozess (wie mit fork(2)) im gleichen
Netzwerk-Namensraum wie der aufrufende Prozess erstellt.
Weitere Informationen zu Netzwerk-Namensräumen finden Sie in network_namespaces(7).
Nur ein privilegierter Prozess (CAP_SYS_ADMIN) kann CLONE_NEWNET angeben.
CLONE_NEWNS (seit Linux 2.4.19)
Wenn der Schalter CLONE_NEWNS gesetzt ist, wird der geklonte Kindprozess in einem neuen,
eingehängten Namensraum gestartet, der mit einer Kopie des Namensraums des Elternprozesses
initialisiert wurde. Wenn CLONE_NEWNS nicht gesetzt ist, bleibt der Kindprozess im gleichen
Namensraum wie der Elternprozess.
Für weitere Informationen über Einhängenamensräume lesen Sie namespaces(7) und mount_namespaces(7)
Nur ein privilegierter Prozess (einer der die Fähigkeit CAP_SYS_ADMIN hat) kann den Schalter
CLONE_NEWNS angeben. Es ist nicht erlaubt, sowohl CLONE_NEWNS als auch CLONE_FS im gleichen Aufruf
von Clone anzugeben.
CLONE_NEWPID (seit Linux 2.6.24)
Wenn CLONE_NEWPID gesetzt ist, dann wird der Prozess in einem neuen PID-Namensraum erstellt. Falls
dieser Schalter nicht gesetzt ist, dann wird der Prozess (wie mit fork(2)) im gleichen
PID-Namensraum wie der aufrufende Prozess erstellt.
Weitere Informationen zu PID-Namensräumen finden Sie in namespaces(7) und pid_namespaces(7).
Nur ein privilegierter Prozess (CAP_SYS_ADMIN) kann CLONE_NEWPID angeben. Dieser Schalter darf
nicht zusammen mit CLONE_THREAD oder CLONE_PARENT angegeben werden.
CLONE_NEWUSER
(Dieser Schalter hatte für clone() erstmals in Linux 2.6.23 eine Bedeutung, die aktuelle
clone()-Semantik wurde in Linux 3.5 aufgenommen und die letzten Anteile, um Benutzernamensräume
komplett nutzbar zu bekommen, wurden in Linux 3.8 aufgenommen.)
Wenn CLONE_NEWUSER gesetzt ist, dann wird der Prozess in einem neuen Benutzer-Namensraum erstellt.
Falls dieser Schalter nicht gesetzt ist, dann wird der Prozess (wie mit fork(2)) im gleichen
Benutzer-Namensraum wie der aufrufende Prozess erstellt.
Für weitere Informationen über Benutzernamensräume lesen Sie namespaces(7) und user_namespaces(7).
Vor Linux 3.8 verlangte die Verwendung von CLONE_NEWUSER, dass der Aufrufende drei Capabilities
hatte: CAP_SYS_ADMIN, CAP_SETUID und CAP_SETGID. Seit Linux 3.8 werden für die Erstellung eines
Benutzernamensraums keine Privilegien benötigt.
Dieser Schalter kann nicht zusammen mit CLONE_THREAD oder CLONE_PARENT angegeben werden. Aus
Sicherheitsgründen darf CLONE_NEWUSER nicht zusammen mit CLONE_FS angegeben werden.
CLONE_NEWUTS (seit Linux 2.6.19)
Falls CLONE_NEWUTS gesetzt ist, erzeugt der Prozess einen neuen UTS-Namensraum, dessen Bezeichner
durch Duplizieren der Bezeichner aus dem UTS-Namensraum des aufrufenden Prozesses initialisiert
werden. Wenn dieser Schalter nicht gesetzt ist (wie mit fork(2)), dann wird der Prozess im
gleichen UTS-Namensraum wie der aufrufende Prozess erzeugt.
Weitere Informationen zu UTS-Namensräumen finden Sie in uts_namespaces(7).
Nur ein privilegierter Prozess (CAP_SYS_ADMIN) kann CLONE_NEWUTS angeben.
CLONE_PARENT (seit Linux 2.3.12)
Falls CLONE_PARENT gesetzt ist, dann wird der Elternprozess des neuen Kindprozesses (wie er von
getppid(2) zurückgegeben wird) der gleiche wie der aufrufende Prozess sein.
Falls CLONE_PARENT nicht gesetzt ist (wie bei fork(2)), dann ist der Elternprozess des
Kindprozesses der aufrufende Prozess.
Beachten Sie, dass dem Elternprozess, wie er von getppid(2) zurückgegeben wird, signalisiert wird
wenn der Kindprozess endet. Wenn also CLONE_PARENT gesetzt ist, wird dem Elternprozess des
aufrufenden Prozesses anstatt dem aufrufenden Prozess selbst das Signal gesandt.
Der Schalter CLONE_PARENT kann in Clone-Aufrufen durch den globalen Init-Prozess (PID 1 im
anfänglichen PID-Namensraum) und in Init-Prozessen in anderen PID-Namensräumen nicht verwandt
werden. Diese Einschränkung verhindert die Erstellung von Prozessbäumen mit mehreren Wurzeln sowie
die Erstellung von nicht zerstörbaren Zombies im anfänglichen PID-Namensraum.
CLONE_PARENT_SETTID (seit Linux 2.5.49)
Die Kindprozess-Thread-Kennung an der Stelle im Elternspeicher ablegen, auf die Eltern_tid
(clone()) oder cl_args.parent_tid (clone3()) zeigt. (In Linux 2.5.32-2.5.48 gab es einen Schalter
CLONE_SETTID, der das tat.) Die Speicheraktion wird abgeschlossen, bevor der Clone-Aufruf die
Steuerung an den Benutzerraum zurückgibt.
CLONE_PID (Linux 2.0 bis 2.5.15)
Falls CLONE_PID gesetzt ist, wird der Kindprozess mit der gleichen Prozesskennung wie der
aufrufende Prozess erstellt. Dies ist gut, um das System zu hacken, aber andererseits zu nicht
viel mehr zu gebrauchen. Seit Linux 2.3.21 konnte dieser Schalter nur durch den Boot-Prozess
festgelegt werden (PID 0). Dieser Schalter verschwand in Linux 2.5.16 komplett aus den
Kernelquellen. In der Folge ignorierte der Kernel dieses Bit, falls es in der Schalter-Maske
angegeben wurde. Viel später wurde das Bit für die Verwendung als Schalter CLONE_PIDFD recyclet.
CLONE_PIDFD (seit Linux 5.2)
Falls dieser Schalter angegeben ist, wird ein PID-Dateideskriptor, der sich auf einen Kindprozess
bezieht, reserviert und an dem angegebenen Ort im Speicher des Elternprozesses abgelegt. Der
Schalter »close-on-exec« wird bei diesem neuen Dateideskriptor gesetzt. PID-Dateideskriptoren
können für die in pidfd_open(2) beschriebenen Zwecke verwandt werden.
• Bei der Verwendung von clone3() wird der PID-Dateideskriptor an dem durch cl_args.pidfd
angezeigten Ort abgelegt.
• Bei der Verwendung von clone() wird der PID-Dateideskriptor an dem Ort abgelegt, auf den
Eltern_tid zeigt. Da das Argument Eltern_tid zur Rückgabe des PID-Dateideskriptors verwandt
wird, kann CLONE_PIDFD beim Aufruf von clone() nicht mit CLONE_PARENT_SETTID benutzt werden.
Es ist derzeit nicht möglich, diesen Schalter zusammen mit CLONE_THREAD zu verwenden. Das
bedeutet, dass ein durch den PID-Dateideskriptor identifizierter Prozess immer der
Prozessgruppenleiter sein wird.
Falls der veraltete Schalter CLONE_DETACHED beim Aufruf von clone() zusammen mit CLONE_PIDFD
angegeben wird, wird ein Fehler zurückgeliefert. Falls CLONE_DETACHED beim Aufruf von clone3()
angegeben wird, wird auch ein Fehler zurückgeliefert. Dieses Fehlerverhalten stellt sicher, dass
das CLONE_DETACHED entsprechende Bit für weitere PID-Dateideskriptorenfunktionalitäten in der
Zukunft recyclet werden kann.
CLONE_PTRACE (seit Linux 2.2)
Falls CLONE_PTRACE angegeben ist und der aufrufende Prozess verfolgt wird, dann wird der
Kindprozess ebenfalls verfolgt (siehe ptrace(2)).
CLONE_SETTLS (seit Linux 2.5.32)
Der TLS (Thread Local Storage)-Deskriptor ist auf tls gesetzt.
Die Interpretation von tls und der resultierende Effekt ist architekturabhängig. Auf X86 ist tls
als ein struct user_desc * interpretiert (siehe set_thread_area(2)). Auf X86-64 ist es der neue
für das Basisregister %fs zu setzende Wert (siehe das Argument ARCH_SET_FS von arch_prctl(2)). Auf
Architekturen mit einem dedizierten TLS-Register ist es der neue Wert dieses Registers.
Der Einsatz dieses Schalters verlangt detaillierte Kenntnisse und sollte im Allgemeinen nicht
erfolgen, außer in einigen Bibliotheken, die Threading implementieren.
CLONE_SIGHAND (seit Linux 2.0)
Ist CLONE_SIGHAND gesetzt, teilen sich der aufrufende Prozess und der Kindprozess die Tabelle der
Signal-Handler. Ruft einer der beiden Prozesse sigaction(2) auf, um das Antwortverhalten auf ein
Signal zu verändern, so betrifft dies auch den anderen Prozess. Jedoch besitzen aufrufender
Prozess und Kindprozess nach wie vor getrennte Signalmasken und getrennte Listen der noch
ausstehenden Signale. Daher könnten Signale durch Aufruf von sigprocmask(2) für einen Prozess
geblockt oder zugelassen werden ohne den anderen Prozess zu beeinflussen.
Ist CLONE_SIGHAND nicht gesetzt, erbt der Kindprozess zum Zeitpunkt des Clone-Aufrufs eine Kopie
des Signal-Handlers vom aufrufenden Prozess. Spätere Aufrufe von sigaction(2) durch einen der
Prozesse hat dann keine Auswirkung auf den anderen Prozess.
Seit Linux 2.6.0 muss die Schalter-Maske außerdem CLONE_VM enthalten, falls CLONE_SIGHAND
angegeben wurde.
CLONE_STOPPED (seit Linux 2.6.0)
Falls CLONE_STOPPED gesetzt ist, ist der Kindprozess anfangs gestoppt (als ob ein SIGSTOP-Signal
gesendet worden wäre) und muss durch Senden eines SIGCONT-Signals wieder aufgenommen werden.
Dieser Schalter war ab Linux 2.6.25 missbilligt und wurde in Linux 2.6.38 vollständig entfernt.
Seitdem ignoriert der Kernel ihn ohne Fehler. Seit Linux 4.6 wird dasselbe Bit für den Schalter
CLONE_NEWCGROUP wiederverwendet.
CLONE_SYSVSEM (seit Linux 2.5.10)
Wenn CLONE_SYSVSEM gesetzt ist, dann teilen sich der Kindprozess und der aufrufende Prozess eine
einzige Liste von System-V-Semaphore-Anpassungswerten, (siehe semop(2)). In diesem Fall sammelt
die gemeinsame Liste semadj Werte über alle Prozesse, die die Liste gemeinsam nutzen und
Semaphore-Anpassungen werden nur durchgeführt, wenn der letzte Prozess, der die Liste gemeinsam
nutzt, sich beendet (oder mittels unshare(2) aufhört, die Liste mitzunutzen). Falls dieser
Schalter nicht gesetzt ist, besitzt der Kindprozess eine separate semadj-Liste, die anfangs leer
ist.
CLONE_THREAD (seit Linux 2.4.0)
Falls CLONE_THREAD gesetzt ist, wird der Kindprozess in die gleiche Thread-Gruppe wie der
aufrufende Prozess platziert. Um den Rest der Diskussion von CLONE_THREAD leserlicher zu machen,
wird der Begriff »Thread« benutzt, um Bezug auf Prozesse innerhalb einer Thread-Gruppe zu nehmen.
Thread-Gruppen waren ein Leistungsmerkmal, das in Linux 2.4 hinzugefügt wurde, um den
POSIX-Thread-Gedanken von einer Thread-Zusammenstellung zu unterstützen, die sich eine einzelne
PID teilt. Intern ist diese gemeinsame PID ein sogenannter Thread-Gruppen-Bezeichner (TGID) für
die Thread-Gruppe. Seit Linux 2.4 geben Aufrufe von getpid(2) die TGID des Aufrufers zurück.
Die Threads innerhalb einer Gruppe können durch ihre (systemweit) einheitliche Thread-Kennung
(TID) unterschieden werden. Die TID eines neuen Threads ist als Funktionsergebnis verfügbar, das
an den Aufrufenden zurückgegeben wird. Ein Thread kann durch Benutzen von gettid(2) seine eigene
TID erhalten.
Wenn Clone ohne Angabe von CLONE_THREAD aufgerufen wurde, dann wird der resultierende Thread in
eine neue Thread-Gruppe platziert, deren TGID der TID des Threads entspricht. Dieser Thread ist
der Führer der neuen Thread-Gruppe.
Ein neuer mit CLONE_THREAD erzeugter Thread hat den gleichen Elternprozess wie der, der Clone
aufrufen hat (d.h. wie CLONE_PARENT), so dass Aufrufe von getppid(2) den gleichen Wert für alle
Threads in der Thread-Gruppe zurückliefern. Wenn ein CLONE_THREAD-Thread endet, wird dem Thread,
der ihn erstellt hat, weder ein SIGCHLD-Signal (oder ein anderes Ende-Signal) gesandt, noch kann
der Status eines solchen Threads per wait(2) abgefragt werden. (Der Thread wird als losgelöst
bezeichnet.)
Nachdem alle Threads in einer Thread-Gruppe beendet sind, wird dem Elternprozess ein
SIGCHLD-Signal (oder ein anderes Ende-Signal) gesandt.
Falls einige der Threads in einer Thread-Gruppe ein execve(2) durchführen, dann werden alle
Threads außer dem Thread-Führer beendet und das neue Programm wird im Thread-Gruppenführer
ausgeführt.
Falls einer der Threads in einer Thread-Gruppe per fork(2) einen Kindprozess erzeugt, dann kann
jeder Thread in der Gruppe wait(2) für diesen Kindprozess ausführen.
Seit Linux 2.5.35 muss die Schalter-Maske auch CLONE_SIGHAND enthalten, wenn CLONE_THREAD
angegeben wurde. Beachten Sie auch, dass seit Linux 2.6.0 CLONE_SIGHAND auch CLONE_VM enthalten
muss.
Signalzuordnungen und -aktionen sind prozessweit: Falls ein nicht abgefangenes Signal an den
Thread geschickt wird, dann wird es alle Mitglieder in der Thread-Gruppe beeinflussen (beenden,
stoppen, fortfahren, darin ignoriert werden).
Jeder Thread hat seine eigene Signalmaske, wie von sigprocmask(2) gesetzt.
Ein Signal kann Prozess-orientiert oder Thread-orientiert sein. Ein Prozess-orientiertes Signal
kann auf eine Thread-Gruppe (d.h. einer TGID) abzielen und wird an einen beliebig ausgewählten
Thread innerhalb dieser, der das Signal nicht blockiert, ausgeliefert. Ein Signal kann
Prozess-orientiert sein, da es vom Kernel aus anderen Gründen (neben
Hardware-Ausnahmebehandlungen) erstellt wurde oder da mittels kill(2) oder sigqueue(3) gesandt
wurde. Ein Thread-orientiertes Signal zielt auf ein bestimmten Thread (d.h. wird an ihn
ausgeliefert). Ein Signal kann Thread-orientiert sein, da es mittels tgkill(2) oder
pthread_sigqueue(3) gesandt wurde oder da der Thread einen Maschinensprachenbefehl ausführte, der
eine Hardware-Ausnahmebehandlung auslöste (z.B. löst ein ungültiger Speicherzugriff SIGSEGV oder
eine Fließkommaausnahmebehandlung SIGFPE aus).
Ein Aufruf von sigpending(2) liefert eine Signalmenge zurück, die die Vereinigung der anhängigen
Prozess-orientierten Signale und der Signale, die für den aufrufenden Thread anhängig sind, ist.
Falls ein Prozess-orientiertes Signal an eine Thread-Gruppe ausgeliefert wird und die
Thread-Gruppe einen Handler für dieses Signal installiert hat, dann dann wird der Handler in exakt
einem willkürlich ausgewählten Mitglied der Thread-Gruppe aufrufen, das das Signal nicht blockiert
hat. Falls mehrere Threads in einer Gruppe darauf warten das gleiche Signal per sigwaitinfo(2) zu
akzeptieren, wird der Kernel einen dieser Threads willkürlich auswählen, um das Signal zu
empfangen.
CLONE_UNTRACED (seit Linux 2.5.46)
Falls CLONE_UNTRACED angegeben ist, kann ein verfolgender Prozess kein CLONE_PTRACE auf diesem
Kindprozess erzwingen.
CLONE_VFORK (seit Linux 2.2)
Falls CLONE_VFORK gesetzt ist, wird die Ausführung des aufrufenden Prozesses aufgeschoben bis der
Kindprozess seine virtuellen Speicherressourcen durch Aufrufen von execve(2) oder _exit(2) (wie
bei vfork(2)) freigibt.
Falls CLONE_VFORK nicht gesetzt ist, dann werden sowohl der aufrufende Prozess, als auch der
Kindprozess nach dem Aufruf planbar und eine Anwendung sollte sich nicht darauf verlassen, dass
die Ausführung in einer speziellen Reihenfolge erfolgt.
CLONE_VM (seit Linux 2.0)
Ist CLONE_VM gesetzt, laufen aufrufender Prozess und Kindprozess im selben Speicherbereich.
Insbesondere sind Schreibzugriffe des aufrufenden Prozesses oder des Kindprozesses in den
gemeinsamen Speicher auch vom anderen Prozess aus sichtbar. Zudem beeinflusst jede Veränderung der
Speicher-Mappings mit mmap(2) oder munmap(2) durch den Kindprozess oder den aufrufenden Prozess
auch den jeweils anderen Prozess.
Ist CLONE_VM nicht gesetzt, erhält der Kindprozess eine eigene Kopie des Speicherbereichs des
aufrufenden Prozesses zum Zeitpunkt des Clone-Aufrufs. Führt ein Prozess Schreibzugriffe auf den
Speicher oder Änderungen am Dateispeicher-Mapping aus, beeinflussen diese Operationen nicht den
jeweils anderen, wie bei fork(2).
Falls der Schalter CLONE_VM angegeben und der Schalter CLONE_VFORK nicht angegeben ist, dann wird
jeder alternative Stapel, der durch sigaltstack(2) etabliert wurde, im Kindprozess bereinigt.
RÜCKGABEWERT
Bei Erfolg wird im ausgeführten Thread des Aufrufenden die Thread-Kennung des Kindprozesses
zurückgegeben. Im Fehlerfall wird im Kontext des Aufrufenden -1 zurückgegeben, kein Kindprozess erzeugt
und errno gesetzt, um den Fehler anzuzeigen.
FEHLER
EACCES (nur clone3())
CLONE_INTO_CGROUP wurde in cl_args.flags angegeben, aber die (in cgroups(7) beschriebenen)
Beschränkungen zum Ablegen des Kindprozesses in die Cgroup der Version 2, auf die sich
cl_args.cgroup bezieht, werden nicht erfüllt.
EAGAIN Es laufen bereits zu viele Prozesse; siehe fork(2).
EBUSY (nur clone3())
CLONE_INTO_CGROUP wurde in cl_args.flags angegeben, aber der in cl_args.cgroup angegebene
Dateideskriptor bezieht sich auf eine Version-2-Cgroup, in der ein Domain-Controller aktiviert
wurde.
EEXIST (nur clone3())
Eine (oder mehrere) der in set_tid festgelegten PIDs existiert im entsprechenden PID-Namensraum
bereits.
EINVAL In der Schalter-Maske wurden sowohl CLONE_SIGHAND als auch CLONE_CLEAR_SIGHAND festgelegt.
EINVAL CLONE_SIGHAND wurde in der Schalter-Maske festgelegt, aber nicht CLONE_VM. (Seit Linux 2.6.0.)
EINVAL CLONE_THREAD wurde in der Schalter-Maske festgelegt, aber nicht CLONE_SIGHAND. (Seit Linux
2.5.35.)
EINVAL CLONE_THREAD wurde in der Schalter-Maske festgelegt, aber der aktuelle Prozess hatte vorher
unshare(2) mit dem Schalter CLONE_NEWPID aufgerufen oder setns(2) verwandt, um sich wieder einem
PID-Namensraum zuzuordnen.
EINVAL In der Schalter-Maske wurden sowohl CLONE_FS als auch CLONE_NEWNS festgelegt.
EINVAL (seit Linux 3.9)
In der Schalter-Maske wurden sowohl CLONE_NEWUSER als auch CLONE_FS festgelegt.
EINVAL In der Schalter-Maske wurden sowohl CLONE_NEWIPC als auch CLONE_SYSVSEM festgelegt.
EINVAL Eines (oder beides) von CLONE_NEWPID oder CLONE_NEWUSER und eines (oder beides) von CLONE_THREAD
oder CLONE_PARENT wurde in der Schalter-Maske festgelegt.
EINVAL (seit Linux 2.6.32)
CLONE_PARENT wurde angegeben und der Aufrufende ist ein Init-Prozess.
EINVAL Wird von der Glibc-Wrapper-Funktion clone() zurückgegeben, wenn ein Wert von NULL für fn oder
Stapel festgelegt wurde.
EINVAL CLONE_NEWIPC wurde in der Schalter-Maske festgelegt, aber der Kernel ist nicht mit den Optionen
CONFIG_SYSVIPC und CONFIG_IPC_NS konfiguriert.
EINVAL CLONE_NEWNET wurde in der Schalter-Maske festgelegt, aber der Kernel ist nicht mit der Option
CONFIG_NET_NS konfiguriert.
EINVAL CLONE_NEWPID wurde in der Schalter-Maske festgelegt, aber der Kernel ist nicht mit der Option
CONFIG_PID_NS konfiguriert.
EINVAL CLONE_NEWUSER wurde in der Schalter-Maske festgelegt, aber der Kernel ist nicht mit der Option
CONFIG_USER_NS konfiguriert.
EINVAL CLONE_NEWUTS wurde in der Schalter-Maske festgelegt, aber der Kernel ist nicht mit der Option
CONFIG_UTS_NS konfiguriert.
EINVAL Stapel ist nicht an einer geeigneten Grenze für diese Architektur ausgerichtet. Beispielsweise
muss Stapel auf Aarch64 ein Vielfaches von 16 sein.
EINVAL (nur clone3())
In der Schalter-Maske wurden CLONE_DETACHED festgelegt.
EINVAL (nur clone())
CLONE_PIDFD wurde zusammen mit CLONE_DETACHED in der Schalter-Maske festgelegt.
EINVAL CLONE_PIDFD wurde zusammen mit CLONE_THREAD in der Schalter-Maske festgelegt.
EINVAL (nur clone())
CLONE_PIDFD wurde zusammen mit CLONE_PARENT_SETTID in der Schalter-Maske festgelegt.
EINVAL (nur clone3())
set_tid_size ist größer als die Anzahl der geschachtelten PID-Namensräume.
EINVAL (nur clone3())
Eine der in set_tid festgelegten PIDs war ungültig.
EINVAL (nur AArch64, Linux 4.6 und älter)
Stapel war nicht an einer 128-Bit-Grenze ausgerichtet.
ENOMEM Es kann nicht ausreichend Speicher für eine Aufgabenstruktur des Kindprozesses reserviert werden
oder um benötigte Teile vom Kontext des Aufrufenden zu kopieren.
ENOSPC (seit Linux 3.7)
CLONE_NEWPID wurde in der Schalter-Maske festgelegt, aber die Begrenzung der Verschachtelungstiefe
von PID-Namensräumen würde überschritten; siehe pid_namespaces(7).
ENOSPC (seit Linux 4.9; vorher EUSERS)
CLONE_NEWUSER wurde in der Schalter-Maske festgelegt und der Aufruf würde zu einer Überschreitung
der Begrenzung für die Anzahl von verschachtelten Benutzernamensräumen führen. Siehe
user_namespaces(7).
Von Linux 3.11 bis Linux 4.8 war der in diesem Fall diagnostizierte Fehler EUSERS.
ENOSPC (seit Linux 4.9)
Einer der Werte in der Schalter-Maske legte die Erstellung eines neuen Benutzer-Namensraums fest,
dadurch würde aber die in der enstprechenden Datei in /proc/sys/user festgelegte Begrenzung
überschritten. Für weitere Details siehe namespaces(7).
EOPNOTSUPP (nur clone3())
CLONE_INTO_CGROUP wurde in cl_args.flags angegeben, aber der in cl_args.cgroup angegebene
Dateideskriptor bezieht sich auf eine Version-2-Cgroup, die im Zustand Domain ungültig ist.
EPERM CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID oder CLONE_NEWUTS wurde von
einem nicht privilegierten Prozess festgelegt (Prozess ohne CAP_SYS_ADMIN).
EPERM CLONE_PID wurde von einem anderen Prozess als Prozess 0 festgelegt. (Dieser Fehler tritt nur unter
Linux 2.5.15 und früheren Versionen auf.)
EPERM CLONE_NEWUSER wurde in der Schalter-Maske festgelegt, aber weder die effektive Benutzerkennung
noch die effektive Gruppenkennung des Aufrufenden hat eine Abbildung in den Namensraum der Eltern
(siehe user_namespaces(7)).
EPERM (seit Linux 3.9)
CLONE_NEWUSER wurde in der Schalter-Maske festgelegt und der Aufrufende ist in einer
Chroot-Umgebung (d.h. das Wurzelverzeichnis des Aufrufenden passt nicht zum Wurzelverzeichnis des
Einhängenamensraums, in dem er sich befindet).
EPERM (nur clone3())
set_tid_size war größer als Null und dem Aufrufenden fehlt in einem oder mehreren
Benutzernamensräumen, dem die entsprechenden PID-Namensräume gehören, die Capability
CAP_SYS_ADMIN.
ERESTARTNOINTR (seit Linux 2.6.17)
Ein Systemaufruf wurde durch ein Signal unterbrochen und wird neu gestartet. (Dies wird nur
während einer Verfolgung sichtbar sein.)
EUSERS (Linux 3.11 bis Linux 4.8)
CLONE_NEWUSER wurde in der Schalter-Maske festgelegt und die Begrenzung für die Anzahl von
verschachtelten Benutzernamensräumen würde überschritten. Siehe die Diskussion des Fehlers ENOSPC
oben.
VERSIONEN
Der Systemaufruf clone3() erschien erstmalig in Linux 5.3.
STANDARDS
Diese Systemaufrufe sind Linux-spezifisch und sollten nicht in portierbaren Programmen benutzt werden.
ANMERKUNGEN
Diese Systemaufrufe werden benutzt, um Threads zu implementieren: mehrere Steuerflüsse in einem Programm,
die gleichzeitig in einem gemeinsamen Speicherbereich ausgeführt werden.
Beachten Sie, dass die Glibc-Wrapperfunktion clone() einige Änderungen am Speicher, auf den Stapel zeigt,
vornimmt (Änderungen, um den Stapel korrekt für das Kind einzurichten), bevor der Systemaufruf clone()
ausgelöst wird. Verwenden Sie daher in Fällen, in denen clone() zur rekursiven Erstellung von Kindern
verwandt wird, nicht den Puffer, der für den Stapel der Eltern eingesetzt wird, als Stapel der Kinder.
Der Systemaufruf kcmp(2) kann zum Testen, ob zwei Prozesse sich verschiedene Ressourcen, wie die
Dateideskriptortabelle, die Rücksetz-Aktionen der System-V-Semaphoren oder einen virtuellen Adressraum,
teilen, verwandt werden.
Handler, die mittels pthread_atfork(3) registriert sind, werden während eines Clone-Aufrufs nicht
ausgeführt.
In der Linux 2.4.x-Serie gibt CLONE_THREAD generell dem neuen Prozess nicht den gleichen Elternprozess,
wie dem aufrufenden Prozess. Für die Linux-Versionen 2.4.7 bis 2.4.18 implizierte der Schalter
CLONE_THREAD jedoch den Schalter CLONE_PARENT (wie in Linux 2.6.0 und neuer).
Auf i386-Architekturen sollte clone() nicht durch vsyscall aufgerufen werden, sondern direkt durch int
$0x80.
Unterschiede C-Bibliothek/Kernel
Der rohe sys_clone-Systemaufruf entspricht eher fork(2), da er mit der Ausführung des Kindprozesses am
Zeitpunkt des Aufrufs fortfährt. Von daher werden die Argumente fn und arg der clone()-Wrapper-Funktion
weggelassen.
Im Gegensatz zum Glibc-Wrapper akzeptiert der rohe Systemaufruf clone() NULL als Stapel-Argument (und
clone3() erlaubt entsprechend cl_args.stack NULL zu sein). In diesem Fall verwendet das Kind eine
Dublette des Stapels des Elternprozesses. (»Copy-on-write«-Semantik stellt sicher, dass der Kindprozess
getrennte Kopien des Stapelspeichers erhält, wenn einer der beiden Prozesse den Stapelspeicher
verändert.) In diesem Fall sollte die Option CLONE_VM nicht angegeben werden, damit es korrekt
funktioniert. (Falls das Kind sich aufgrund des Schalters CLONE_VM mit dem Elternprozess den Speicher
teilt, dann tritt keine copy-on-write-Duplizierung auf und wahrscheinlich tritt Chaos ein.
Die Reihenfolge der Argumente unterscheidet sich auch im rohen Systemaufruf und es gibt über die
Architekturen hinweg Variationen in den Argumenten, wie dies in den folgenden Absätzen dargestellt wird.
Die rohe Schnittstelle für Systemaufrufe auf x86-64 und einigen anderen Architekturen (darunter Sh, Tile
und Alpha) sieht so aus:
long clone(unsigned long Schalter, void *Stapel,
int *Eltern_tid, int *Kind_tid,
unsigned long tls);
Auf x86-32 und mehreren anderen häufigen Architekturen (darunter Score, ARM, ARM 64, PA-RISC, Arc, Power
PC, Xtensa und MIPS) ist die Reihenfolge der letzten zwei Argumente gedreht:
long clone(unsigned long Schalter, void *Stapel,
int *Eltern_tid, unsigned long tls,
int *Kind_tid);
Auf der Cris- und S30-Architektur ist die Reihenfolge der ersten zwei Argumente gedreht:
long clone(void *Stapel, unsigned long Schalter,
int *Eltern_tid, int *Kind_tid,
unsigned long tls);
Auf der Microblaze-Architektur wird ein zusätzliches Argument übergeben:
long clone(unsigned long Schalter, void *Stapel,
int Stapelgröße, /* Größe des Stapels */
int *Eltern_tid, int *Kind_tid,
unsigned long tls);
Blackfin, M68k und Sparc
Die Konventionen der Argumentübergabe weichen auf Blackfin, M68k und Sparc von der obigen Beschreibung
ab. Einzelheiten finden Sie in der Kernel- (und Glibc-) Quelle.
Ia64
Auf ia64 wird eine andere Schnittstelle benutzt:
int __clone2(int (*fn)(void *),
void *Stapelbasis, size_t Stapelgröße,
int Schalter, void *arg, …
/* pid_t *Eltern_tid, struct user_desc *tls,
pid_t *Kind_tid */ );
Der oben gezeigte Prototyp ist für die Glibc-Wrapper-Funktion; für den Systemaufruf selbst wird der
Prototyp wie folgt beschrieben (er ist identisch zum clone()-Prototyp auf Microblaze):
long clone2(unsigned long Schalter, void *Stapelbasis,
int Stapelgröße, /* Größe des Stapels */
int *Eltern_tid, int *Kind_tid,
unsigned long tls);
__clone2() arbeitet auf die gleiche Weise wie clone(), außer dass Stapelbasis auf die niedrigste Adresse
im Stapelspeicherbereich des Kindprozesses zeigt und Stapelgröße die Größe des Stapelspeichers angibt,
auf die Stapelbasis zeigt.
Linux 2.4 und älter
Unter Linux 2.4 und früher gab es die Argumente Eltern_tid, tls und Kind_tid noch nicht.
FEHLER
GNU-C-Bibliotheksversionen 2.3.4 bis einschließlich 2.24 enthielten eine Wrapper-Funktion für getpid(2),
die Zwischenspeichern von PIDs vornahm. Dieses Zwischenspeichern beruhte auf der Unterstützung in dem
Glibc-Wrapper von clone(), aber Einschränkungen in der Implementierung bedeuteten, dass unter einigen
Umständen der Zwischenspeicher nicht aktuell war. Insbesondere wenn ein Signal sofort nach dem
clone()-Aufruf an den Kindprozess gesandt wurde, konnte ein Aufruf von getpid(2) in einem Signal-Handler
die PID des aufrufenden Prozesses (des »Elternprozesses«) zurückgeben, falls der Clone-Wrapper noch keine
Chance hatte den PID-Zwischenspeicher im Kindprozess zu aktualisieren. (Diese Diskussion ignoriert den
Fall, dass der Kindprozess mit CLONE_THREAD erstellt wurde, in dem getpid(2) den gleichen Wert im
Kindprozess zurückgeben sollte und im Prozess, der clone() aufrief, wie sich der Aufrufende und der
Kindprozess in der gleichen Thread-Gruppe befinden. Das Problem des nicht mehr frischen Zwischenspeichers
tritt auch auf, wenn das Argument Schalter CLONE_VM enthält.) Um die Wahrheit zu erfahren, war es
manchmal notwendig gewesen, Code wie den folgenden zu verwenden:
#include <syscall.h>
pid_t mypid;
mypid = syscall(SYS_getpid);
Aufgrund des Problems mit dem nicht mehr frischem Zwischenspeicher sowie anderen in getpid(2) bemerkten
Problemen, wurde die Funktionalität des PID-Zwischenspeicherns in Glibc 2.25 entfernt.
BEISPIELE
Das folgende Programm demonstriert die Benutzung von clone() zum Erzeugen eines Kindprozesses, der in
einem separaten UTS-Namensraum ausgeführt wird. Der Kindprozess ändert in seinem UTS-Namensraum den
Rechnernamen. Dann zeigen sowohl Eltern- als auch Kindprozess den Rechnernamen des Systems an, wodurch
sichtbar wird, dass der Rechnername sich im UTS-Namensraum von Eltern- und Kindprozess unterscheidet. Ein
Beispiel für die Verwendung dieses Programms finden Sie in setns(2).
Innerhalb des Beispielprogramms reservieren wir Speicher, der für den Stapel des Kindprogramms verwandt
werden soll. Dabei verwenden wir aus den folgenden Gründen mmap(2) statt malloc(3):
• mmap(2) reserviert einen Speicherblock, der an einer Seitengrenze beginnt und ein Vielfaches der
Seitengröße groß ist. Dies ist nützlich, um am Ende des Stapels mittels mprotect(2) eine Wächterseite
(eine Seite mit dem Schutz PROT_NONE) einzurichten.
• Wir können den Schalter MAP_STACK angeben, um ein für den Stapel geeignetes Mapping festzulegen.
Derzeit führt dieser Schalter unter Linux zu keiner Aktion, aber er existiert und hat auf anderen
Systemen Auswirkungen, daher sollten wir ihn zwecks Portabilität aufnehmen.
Programmquelltext
#define _GNU_SOURCE
#include <err.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
static int /* Startfunktion für geklonten Kindprozess */
childFunc(void *arg)
{
struct utsname uts;
/* Rechnername im UTS-Namensraum des Kindprozesses ändern. */
if (sethostname(arg, strlen(arg)) == -1)
err(EXIT_FAILURE, "sethostname");
/* Rechnernamen abfragen und anzeigen. */
if (uname(&uts) == -1)
err(EXIT_FAILURE, "uname");
printf("uts.nodename im Kindprozess: %s\n", uts.nodename);
/* Der Namensraum wird für eine Weile durch Schlafen offen gehalten.
Dies ermöglicht etwas zu experimentieren – zum Beispiel
kann ein weiterer Prozess dem Namensraum beitreten. */
sleep(200);
return 0; /* Kindprozess wird nun beendet */
}
#define STACK_SIZE (1024 * 1024) /* Stapelspeichergröße für geklonten
Kindprozess */
int
main(int argc, char *argv[])
{
char *stack; /* Start des Stapelspeicherpuffers */
char *stackTop; /* Ende des Stapelspeicherpuffers */
pid_t pid;
struct utsname uts;
if (argc < 2) {
fprintf(stderr, "Aufruf: %s <Kindprozess-Rechnername>\n", argv[0]);
exit(EXIT_SUCCESS);
}
/* Speicher für den Stapel des Kindprozess reservieren. */
stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED)
err(EXIT_FAILURE, "mmap");
stackTop = stack + STACK_SIZE; /* Annahme, dass Stapelspeicher nach
unten wächst */
/* Es wird ein Kindprozess erzeugt, der seinen eigenen Namensraum hat.
Der Kindprozess beginnt die Ausführung in childFunc(). */
pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
if (pid == -1)
err(EXIT_FAILURE, "clone");
printf("clone() gab %jd zurück\n", (intmax_t) pid);
/* Elternprozess fällt bis hierher durch */
sleep(1); /* gibt dem Kindprozess Zeit zum Ändern des Rechnernamens */
/* Den Rechnernamen im UTS-Namensraum des Elternprozesses anzeigen.
Dieser wird sich vom Rechnernamen im UTS-Namensraum des Kindprozesses
unterscheiden. */
if (uname(&uts) == -1)
err(EXIT_FAILURE, "uname");
printf("uts.nodename im Elternprozess: %s\n", uts.nodename);
if (waitpid(pid, NULL, 0) == -1) /* Warten auf Kindprozess */
err(EXIT_FAILURE, "waitpid");
printf("Kindprozess wurde beendet\n");
exit(EXIT_SUCCESS);
}
SIEHE AUCH
fork(2), futex(2), getpid(2), gettid(2), kcmp(2), mmap(2), pidfd_open(2), set_thread_area(2),
set_tid_address(2), setns(2), tkill(2), unshare(2), wait(2), capabilities(7), namespaces(7), pthreads(7)
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Daniel Kobras <kobras@linux.de>, Chris Leick
<c.leick@vollbio.de>, Mario Blättermann <mario.blaettermann@gmail.com>, Dr. Tobias Quathamer
<toddy@debian.org> und Helge Kreutzmann <debian@helgefjell.de> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer
bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die
Mailingliste der Übersetzer.
Linux man-pages 6.03 5. Februar 2023 clone(2)