BEZEICHNUNG¶
clone, __clone2 - erzeugt einen Kindprozess
ÜBERSICHT¶
#define _GNU_SOURCE /* Siehe feature_test_macros(7) */
#include <sched.h>
int clone(int (*fn)(void *), void *kind_stack,
int schalter, void *arg, ...
/* pid_t *ptid, struct user_desc *tls,
pid_t *ctid */ );
BESCHREIBUNG¶
clone() erzeugt einen neuen Prozess auf eine ähnliche Art wie
fork(2) Tatsächlich ist es eine Bibliotheksfunktion, die zuoberst
auf dem darunterliegenden Systemaufruf
clone() aufsetzt, nachfolgend
sys_clone genannt. Eine Beschreibung von
sys_clone findet sich
gegen Ende dieser Seite.
Im Gegensatz zu
fork(2) erlauben diese Aufrufe, dass der Kindprozess
Teile seines Kontextes mit dem aufrufenden Prozess teilt. Dazu zählen der
Speicherplatz, die Tabelle der Dateideskriptoren und die Tabelle der
Signal-Handler. (Beachten Sie, dass »aufrufender Prozess« auf dieser
Handbuchseite »Elternprozess« entspricht. Aber lesen Sie im
Folgenden die Beschreibung von
CLONE_PARENT.)
Hauptsächlich wird
clone() benutzt, um Threads zu implementieren:
mehrere Steuer-Threads in einem Programm, die gleichzeitig in einem
gemeinsamen Speicherbereich ausgeführt werden.
Wird mit
clone() ein Kindprozess erzeugt, führt er das
Funktionsprogramm
fn(
arg) aus. (Dies ist ein Unterschied zu
fork(2), wo die Ausführung im Kindprozess vom Punkt des
fork(2)-Aufrufs fortfährt.) Das Argument
fn ist ein Zeiger
auf eine Funktion, die vom Kindprozess zu Beginn seiner Ausführung
abgearbeitet wird.
arg wird der Funktion
fn als Argument
übergeben.
Kehrt die Funktion
fn(
arg) zurück, so beendet sich der
Kindprozess. Der Ganzzahlwert, der von
fn zurückgeliefert wird,
entspricht dem Exit-Code des Kindprozesses. Der Kindprozess kann auch durch
den expliziten Aufruf von
exit(2) oder durch den Empfang eines fatalen
Signals beendet werden.
Das Argument
kind_stack 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
kind_stack für gewöhnlich auf die oberste
Adresse im bereitgehaltenen Speicherbereich zeigt.
Das niederwertige Byte von
schalter enthält die Nummer des
Beendigungssignals, das an den Elternprozess gesandt wird, wenn der
Kindprozess endet. 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 angegeben wurde, wird dem Elternprozess nicht
signalisiert, wenn der Kindprozess endet.
schalter kann darüber hinaus noch durch bitweises »Oder«
mit keiner oder mehreren der folgenden Konstanten verknüpft werden.
Dadurch wird festgelegt, welche Ressourcen sich Eltern- und Kindprozess
teilen:
- CLONE_CHILD_CLEARTID (seit Linux 2.5.49)
- Kind-Thread-ID an der Stelle ctid im Kindspeicher
löschen, wenn das Kind existiert 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-ID an der Stelle ctid im
Kindspeicher
- CLONE_FILES
- 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.
Ist CLONE_FILES nicht gesetzt, erbt der Kindprozess zur
Ausführungszeit von clone() eine Kopie der aktuell
geöffneten Dateideskriptoren. (Die kopierten Dateideskriptoren im
Kindprozess beziehen sich auf die gleichen offenen Dateideskriptoren
(siehe open(2)) wie die entsprechenden Dateideskriptoren im
aufrufenden Prozess.) Anschließende Operationen, 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.
- CLONE_FS
- 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 von
clone() mit einer Kopie der Dateisysteminformationen des
aufrufenden Prozesses zur Zeit des clone()-Aufrufs. Spätere
Aufrufe von chroot(2), chdir(2) und umask(2)
beeinflussen den anderen Prozess nicht.
- 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-Steuerprogramms, d.h., welches das E/A-Steuerprogramm zur
Modellplanung für E/As des Prozesses benutzt. Falls sich Prozesse den
gleichen E/A-Kontext teilen, werden sie vom E/A-Steuerprogramm als ein
einziger betrachtet. Als Konsequenz daraus müssen sie sich die
gleiche Plattenzeitzugriffzeit teilen. Einige E/A-Steuerprogramme
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_NEWIPC (seit Linux 2.6.19)
- Ist CLONE_NEWIPC gesetzt, dann wird der Prozess in
einem neuen IPC-Namensraum erstellt. Falls dieser Schalter nicht gesetzt
ist, dann wird der Prozess (wie bei fork(2)) im gleichen
IPC-Namensraum wie der aufrufende Prozess erstellt. Dieser Schalter ist
für die Implementierung von Containern gedacht.
Ein IPC-Namensraum besteht aus einer Zusammenstellung von Bezeichnern
für System-V-IPC-Objekte. (Zur Erstellung dieser Objekte wurden
msgctl(2), semctl(2) und shmctl(2) benutzt). Objekte,
die in einem IPC-Namensraum erstellt wurden, sind für alle anderen
Prozesse sichtbar, die Mitglieder des Namensraums sind. Die Objekte sind
jedoch nicht für Prozesse in anderen Namensräumen sichtbar.
Wenn ein IPC-Namensraum zerstört wird, d.h., wenn der letzte Prozess im
Namensraum beendet wird, werden alle IPC-Objekte im Namensraum automatisch
zerstört.
Die Benutzung dieses Schalters benötigt einen Kernel, der mit den
Optionen CONFIG_SYSVIPC und CONFIG_IPC_NS konfiguriert
wurde, und erfordert, dass der Prozess privilegiert ist ((
CAP_SYS_ADMIN). Dieser Schalter kann nicht in Verbindung mit
CLONE_SYSVSEM angegeben werden.
- CLONE_NEWNET (seit Linux 2.6.24)
- (Die Implementierung dieses Schalters wurde erst mit der
Kernel-Version 2.6.29 abgeschlossen.)
Wenn CLONE_NEWNET gesetzt ist, dann wird der Prozess einen 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. Dieser Schalter
ist für die Implementierung von Containern gedacht.
Ein Netzwerk-Namensraum stellt eine isolierte Ansicht des
Netzwerk-Stapelspeichers (Netzwerkgeräteschnittstellen, IPv4- und
IPv6-Protokoll-Stapelspeicher, IP-Routing-Tabellen, Firewall-Regeln, die
Verzeichnisbäume /proc/net und /sys/class/net, Sockets,
etc.) bereit. Ein physisches Netzwerkgerät kann in genau einem
Netzwerknamensraum bestehen. Ein virtuelles Netzwerkgerätepaar
(»veth«) stellt eine einer Pipe ähnliche Abstraktion
bereit, die benutzt werden kann, um Tunnel zwischen
Netzwerk-Namensräumen aufzubauen und eine Brücke in ein
physisches Netzwerkgerät in einem anderen Namensraum zu erstellen.
Wenn ein Netzwerk-Namensraum freigegeben wird, d.h. wenn der letzte Prozess
im Namensraum beendet wird, werden seine physischen Netzwerkgeräte
zurück in den ursprünglichen Namensraum verschoben (nicht zum
Elternprozess).
Die Benutzung dieses Schalters benötigt einen Kernel, der mit der
Option CONFIG_NET_NS konfiguriert wurde, und einen privilegierten
Prozess ( CAP_SYS_ADMIN).
- CLONE_NEWNS (seit Linux 2.4.19)
- Den Kindprozess in einem neu eingehängten Namensraum
starten
Jeder Prozess »lebt« in einem Namensraum. Der Namensraum
eines Prozesses besteht aus den Daten (den eingehängten
Zusammenstellungen), die die Dateihierarchie beschreiben, wie sie von
diesem Prozess gesehen wird. Nach einem fork(2) oder
clone(), bei dem der Schalter CLONE_NEWNS nicht gesetzt ist,
»lebt« der Kindprozess im gleichen eingehängten Namensraum,
wie der Elternprozess. Die Systemaufrufe mount(2) und
umount(2) ändern den eingehängten Namensraum des
aufrufenden Prozesses und beeinflussen daher alle Prozesse im gleichen
Namensraum, jedoch keine Prozesse in einem anderen eingehängten
Namensraum.
Nach einem clone(), bei dem 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.
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 (wie mit fork(2)), dann wird der Prozess in dem
gleichen PID-Namensraum wie der aufrufende Prozess erstellt. Der Schalter
ist für die Implementierung von Containern gedacht.
Ein PID-Namensraum stellt eine isolierte Umgebung für PIDs bereit: PIDs
in einem neuen Namensraum beginnen bei 1, etwa wie ein alleinstehendes
System und Aufrufe wie fork(2), vfork(2) oder clone()
werden Prozesse mit PIDs erstellen, die innerhalb dieses Namensraums
eindeutig sind.
Der erste Prozess, der in einem neuen Namensraum erstellt wird, d.h. der
Prozess, der unter Benutzung des Schalters CLONE_NEWPID erstellt
wird hat die PID 1 und ist der »init«-Prozess dieses
Namensraums. Kindprozesse, die innerhalb des Namensraums verwaist sind,
werden eher diesem Prozess untergeordnet als init(8). Im Gegensatz
zum traditionellen init-Prozess kann der »init«-Prozess
eines PID-Namensraums beendet werden. Wenn dies geschieht, werden alle
Prozesse im Namensraum beendet.
PID-Namensräume bilden eine Hierarchie. Wenn ein neuer PID-Namensraum
erzeugt wird, sind die Prozesse in diesem Namensraum im PID-Namensraum des
Prozesses sichtbar, der den Prozess im neuen Namensraum erzeugt hat; ist
entsprechend der Eltern-PID-Namensraum selbst Kind eines anderen
PID-Namensraums, dann sind sowohl Kind- als auch Eltern-PID-Namensraum im
Großeltern-Namensraum sichtbar. Umgekehrt sehen die Prozesse im
»Kind«-PID-Namensraum nicht die Prozesse im Eltern-Namensraum.
Die Existenz einer Namensraum-Hierarchie bedeutet, dass jeder Prozess nun
mehrere PIDs haben kann: einen für jeden Namensraum, in dem er
sichtbar ist; jede dieser PIDs ist innerhalb des dazugehörigen
Namensraums eindeutig. (Ein Aufruf von getpid(2) gibt immer die PID
für den Namensraum zurück, in der der Prozess »lebt«.)
Nach dem Erstellen eines neuen Namensraums ist es für den Kindprozess
nützlich, sein Wurzelverzeichnis zu ändern und eine neue
Procfs-Instanz in /proc einzuhängen, so dass Werkzeuge wie
ps(1) korrekt arbeiten. (Falls außerdem CLONE_NEWNS zu
den Schaltern gehört, dann ist es nicht nötig das
Wurzelverzeichnis zu ändern: Eine neue Procfs-Instanz kann direkt
über /proc eingehängt werden.)
Die Benutzung dieses Schalters benötigt einen Kernel, der mit der
Option CONFIG_PID_NS konfiguriert wurde und einen privilegierten
Prozess ( CAP_SYS_ADMIN). Dieser Schalter kann nicht zusammen mit
CLONE_THREAD 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. Dieser Schalter ist für die Implementierung von
Containern gedacht.
Ein UTS-Namensraum ist eine Zusammenstellung von Bezeichnern, die von
uname(2) zurückgegeben werden; von denen können der
Domain-Name und der Rechnername durch setdomainname(2)
beziehungsweise sethostname(2) geändert werden.
Änderungen, die an Bezeichnern in einem UTS-Namensraum vorgenommen
werden, sind für alle anderen Prozesse im gleichen Namensraum
sichtbar, nicht jedoch für Prozesse in anderen UTS-Namensräumen.
Die Benutzung dieses Schalters setzt einen Kernel voraus, der mit der Option
CONFIG_UTS_NS konfiguriert wurde und dass der Prozess privilegiert
ist ( CAP_SYS_ADMIN).
- 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.
- CLONE_PARENT_SETTID (seit Linux 2.5.49)
- Kindprozess-Thread-ID an Stelle ptid im Eltern- und
Kindspeicher ablegen. (In Linux 2.5.32-2.5.48 gab es einen Schalter
CLONE_SETTID, der das tat.)
- CLONE_PID (veraltet)
- Falls CLONE_PID gesetzt ist, wird der Kindprozess
mit der gleichen Prozess-ID wie der aufrufende Prozess erstellt. Dies ist
gut, um das System zu hacken, aber andererseits zu nicht viel mehr zu
gebrauchen. Seit 2.3.21 konnte dieser Schalter nur durch den Boot-Prozess
angegeben werden (PID 0). Er verschwand in Linux 2.5.16.
- CLONE_PTRACE
- 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)
- Das Argument newtls ist der neue TLS-Desktiptor
(Thread Local Storage). (Lesen Sie set_thread_area(2).)
- CLONE_SIGHAND
- 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. Einzelne Signale könnten daher 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 durch den
clone-Aufruf 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-test6 müssen die schalter außerdem
CLONE_VM enthalten, falls CLONE_SIGHAND angegeben
wurde.
- CLONE_STOPPED (seit Linux 2.6.0-test2)
- 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.
- 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 Werten, um
System-V-Semaphoren rückgängig zu machen (siehe
semop(2)). Falls dieser Schalter nicht gesetzt ist, besitzt der
Kindprozess eine eigene List zum Rückgängig machen, die anfangs
leer ist.
- CLONE_THREAD (seit Linux 2.4.0-test8)
- 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-ID (TID) unterschieden werden. Die TID eines neuen
Threads ist als Funktionsergebnis verfügbar, das an den Aufrufenden
von clone() 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() aufruft (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 per
clone() 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 müssen die schalter auch CLONE_SIGHAND
enthalten, wenn CLONE_THREAD angegeben wurde.
Signale können an eine Thread-Gruppe als Ganzes geschickt werden (d.h.
einer TGID) unter Benutzung von kill(2) oder an einen bestimmten
Thread unter Benutzung von tgkill(2).
Signalanordnungen 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 sie von sigprocmask(2)
gesetzt wird, Signale können aber entweder für den ganzen
Prozess anstehen (d.h. an jedes Mitglied der Thread-Gruppe zu liefern
sein), wenn sie mit kill(2) gesandt wurden oder für einen
einzelnen Thread, wenn sie mit tgkill(2) gesandt wurden. Ein Aufruf
von sigpending(2) gibt eine Signalzusammenstellung zurück, die
eine Verbindung ausstehender Signale für den ganzen Prozess und der
Signale ist, die für den aufrufenden Prozess anstehen.
Falls kill(2) benutzt wird, um ein Signal an eine Thread-Gruppe zu
senden 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 per kill(2) gesandt 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
- 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
- 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 zur Zeit 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).
sys_clone¶
Der
sys_clone-Systemaufruf entspricht eher
fork(2), der 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. Zudem wird die Reihenfolge der
Argumente geändert. Die grobe Schnittstelle für Systemaufrufe ist
ungefähr:
long clone(unsigned long schalter, void *kind_stack,
void *ptid, void *ctid,
struct pt_regs *regs);
Ein weiterer Unterschied für
sys_clone besteht darin, dass das
Argument
kind_stack Null sein könnte, so dass in diesem Fall
»copy-on-write«-Semantik sicherstellt, dass der Kindprozess
getrennte Kopien des Stapelspeichers erhält, wenn beide Prozesse den
Stapelspeicher verändern. In diesem Fall sollte die Option
CLONE_VM nicht angegeben werden, damit es korrekt funktioniert.
Linux 2.4 und früher¶
Unter Linux 2.4 und früher gab es die Argumente
ptid,
tls und
ctid noch nicht.
RÜCKGABEWERT¶
Bei Erfolg wird im ausgeführten Thread des Aufrufenden die Thread-ID des
Kindprozesses zurückgegeben. Im Fehlerfall wird im Kontext des
Aufrufenden -1 zurückgegeben, kein Kindprozess erzeugt und
errno
entsprechend gesetzt.
FEHLER¶
- EAGAIN
- Es laufen bereits zu viele Prozesse.
- EINVAL
- CLONE_SIGHAND wurde angegeben, aber nicht
CLONE_VM. (Seit Linux 2.6.0-test6.)
- EINVAL
- CLONE_THREAD wurde angegeben, aber nicht
CLONE_SIGHAND. (Seit Linux 2.5.35.)
- EINVAL
- In schalter wurden sowohl CLONE_FS als auch
CLONE_NEWNS angegeben.
- EINVAL
- In schalter wurden sowohl CLONE_NEWIPC als
auch CLONE_SYSVSEM angegeben.
- EINVAL
- In schalter wurden sowohl CLONE_NEWPID als
auch CLONE_THREAD angegeben.
- EINVAL
- Wird von clone() zurückgegeben, wenn ein Wert
von Null für kind_stack angegeben wurde.
- EINVAL
- In schalter wurde CLONE_NEWIPC angegeben, der
Kernel wurde jedoch nicht mit den Optionen CONFIG_SYSVIPC und
CONFIG_IPC_NS konfiguriert.
- EINVAL
- In schalter wurde CLONE_NEWNET angegeben, der
Kernel wurde jedoch nicht mit der Option CONFIG_NET_NS
konfiguriert.
- EINVAL
- In schalter wurde CLONE_NEWPID angegeben, der
Kernel wurde jedoch nicht mit der Option CONFIG_PID_NS
konfiguriert.
- EINVAL
- In schalter wurde CLONE_NEWUTS angegeben, der
Kernel wurde jedoch nicht mit der Option CONFIG_UTS
konfiguriert.
- 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.
- EPERM
- CLONE_NEWIPC, CLONE_NEWNET,
CLONE_NEWNS, CLONE_NEWPID oder CLONE_NEWUTS wurde von
einem nicht privilegierten Prozess angegeben (Prozess ohne
CAP_SYS_ADMIN).
- EPERM
- CLONE_PID wurde von einem anderen Prozess als
Prozess 0 angegeben.
VERSIONEN¶
Es gibt in libc5 keinen
clone()-Eintrag. glibc2 stellt
clone(),
wie in dieser Handbuchseite beschrieben, zur Verfügung.
Die Aufrufe
clone() und
sys_clone sind Linux-spezifisch und
sollten nicht in portablen Programmen benutzt werden.
ANMERKUNGEN¶
In den 2.4.x-Kerneln gibt
CLONE_THREAD generell dem neuen Prozess nicht
den gleichen Elternprozess, wie dem aufrufenden Prozess. Für die
Kernel-Versionen 2.4.7 bis 2.4.18 implizierte der Schalter
CLONE_THREAD
jedoch den Schalter
CLONE_PARENT (wie in Kernel 2.6).
Für eine Weile gab es
CLONE_DETACHED (eingeführt in 2.5.32):
Elternprozesse wollen kein Ende-Signal des Kindprozesses. In 2.6.2 verschwand
die Notwendigkeit, dies zusammen mit
CLONE_THREAD zu übergeben.
Dieser Schalter ist immer noch definiert, hat aber keine Auswirkungen.
Auf i386-Architekturen sollte
clone() nicht durch vsyscall aufgerufen
werden, aber direkt durch
int $0x80.
Auf ia64-Architekturen wird ein anderer Systemaufruf benutzt:
int __clone2(int (*fn)(void *),
void *kind_stack_basis, size_t stack_groesse,
int schalter, void *arg, ...
/* pid_t *ptid, struct user_desc *tls,
pid_t *ctid */ );
Der Systemaufruf
__clone2() arbeitet auf die gleiche Weise wie
clone(), außer dass
kind_stack_basis auf die niedrigste
Adresse im Stapelspeicherbereich des Kindprozesses zeigt und
stack_groesse die Größe des Stapelspeichers angibt, auf die
kind_stack_basis zeigt.
FEHLER¶
Versionen der GNU-C-Bibiliothek, die die NPTL-Threading-Bibliothek enthalten,
enthalten eine Wrapper-Funktion für
getpid(2), die die
Zwischenspeicherung der PIDs verrichtet. Diese Zwischenspeicherung beruht auf
der Unterstützung für
clone() im Glibc-Wrapper, der
Zwischenspeicher könnte aber der derzeitigen Implementierung unter
Umständen nicht aktuell sein. Insbesondere wenn ein Signal sofort nach
dem
clone()-Aufruf an den Kindprozess gesandt wird, könnte 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, könnte es
nötig sein Kode wie den folgenden zu verwenden:
#include <syscall.h>
pid_t mypid;
mypid = syscall(SYS_getpid);
SIEHE AUCH¶
fork(2),
futex(2),
getpid(2),
gettid(2),
set_thread_area(2),
set_tid_address(2),
tkill(2),
unshare(2),
wait(2),
capabilities(7),
pthreads(7)
KOLOPHON¶
Diese Seite ist Teil der Veröffentlichung 3.42 des Projekts Linux-
man-pages. Eine Beschreibung des Projekts und Informationen, wie Fehler
gemeldet werden können, finden sich unter
http://www.kernel.org/doc/man-pages/.
ÜBERSETZUNG¶
Die deutsche Übersetzung dieser Handbuchseite wurde von Daniel Kobras
<kobras@linux.de> und Chris Leick <c.leick@vollbio.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 <debian-l10n-german@lists.debian.org>.