clone(2) System Calls Manual clone(2) BEZEICHNUNG clone, __clone2, clone3 - erzeugt einen Kindprozess BIBLIOTHEK Standard-C-Bibliothek (libc, -lc) UBERSICHT /* Prototyp fur die Glibc-Wrapper-Funktion */ #define _GNU_SOURCE #include 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 */ ); /* Fur den Prototyp des rohen clone()-Systemaufrufs siehe ANMERKUNGEN */ #include /* Definition von struct clone_args */ #include /* Definition der CLONE_*-Konstanten */ #include /* Definition der SYS_*-Konstanten */ #include long syscall(SYS_clone3, struct clone_args *cl_args, size_t groesse); Hinweis: Glibc stellt keinen Wrapper fur clone3() bereit; rufen Sie ihn mittels syscall(2) auf. BESCHREIBUNG Diese Systemaufrufe erzeugen auf eine ahnliche Weise wie fork(2) einen neuen Prozess (>>Kind<<). Im Gegensatz zu fork(2) bieten diese Systemaufrufe eine genauere Kontrolle daruber, welche Teile des Ausfuhrungskontextes 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 ermoglichen 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: o Die clone()-Wrapper-Funktion von Glibc als auch den darunterliegenden Systemaufruf, auf dem sie basiert. Der Haupttext erklart die Wrapper-Funktion. Die Unterschiede zum rohen Systemaufruf werden gegen Ende dieser Seite erlautert. o Der neuere Systemaufruf clone3(). Im Rest der Seite wird die Terminologie >>der Clone-Aufruf<< verwandt, wenn Details erklart werden, die auf alle diese Schnittstellen zutreffen. Die clone()-Wrapper-Funktion Wird mit der clone()-Wrapper-Funktion ein Kindprozess erzeugt, beginnt es die Ausfuhrung durch Aufruf der Funktion, auf die das Argument fn zeigt. (Dies ist ein Unterschied zu fork(2), wo die Ausfuhrung im Kindprozess vom Punkt des fork(2)-Aufrufs fortfahrt.) Das Argument arg wird als Argument der Funktion fn ubergeben. Kehrt die Funktion fn(arg) zuruck, so beendet sich der Kindprozess. Der Ganzzahlwert, der von fn zuruckgeliefert 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 konnen, kann der Kindprozess nicht auf dem selben Stapelspeicher wie der aufrufende Prozess laufen. Der aufrufende Prozess muss daher einen Speicherbereich als Stapelspeicher fur den Kindprozess bereithalten und per clone einen Zeiger darauf an den Kindprozess ubergeben. Der Stapelspeicher wachst (mit Ausnahme der PA-Prozessoren von HP) auf allen von Linux unterstutzten Prozessoren nach unten, so dass Stapel fur gewohnlich auf die oberste Adresse im bereitgehaltenen Speicherbereich zeigt. Beachten Sie, dass clone() keine Moglichkeit bereitstellt, mit der der Aufrufende den Kernel uber die Grosse des Stapel-Bereichs informieren konnte. Die verbliebenen Argumente fur clone() werden unten behandelt. clone3() Der Systemaufruf clone3() stellt eine Obermenge der Funktionalitat der alteren Schnittstelle clone() bereit. Er stellt auch eine Reihe von API-Verbesserungen bereit, einschliesslich: Platz fur zusatzliche Schalter-Bits; deutlichere Trennung beim Einsatz der verschiedenen Argumente, die Moglichkeit, die Grosse des Stapel-Bereichs des Kindprozesses festzulegen. Wie bei fork(2) kehrt clone3() sowohl im Eltern- als auch im Kindprozess zuruck. Er liefert 0 im Kindprozess und die PID des Kindprozesses im Elternprozess zuruck. 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; /* Grosse 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 fur Ziel-Cgroup eines Kindes (seit Linux 5.7) */ }; Das an clone3() ubergebene Argument groesse sollte auf die Grosse dieser Struktur initialisiert werden. (Die Existenz des Arguments groesse ermoglicht zukunftige Erweiterungen der clone_args-Struktur.) Der Stapel fur den Kindprozess wird in cl_args.stack, der auf das niedrigste Byte des Stapel-Bereichs zeigt, und cl_args.stack_size, der die Grosse 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 konnen 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. Aquivalenz zwischen den Argumenten von clone() und clone3() Anders als die altere clone()-Schnittstelle, bei der die Argumente individuell ubergeben 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 uber die clone()-Argumente ubergeben wird. Die folgende Tabelle zeigt die Aquivalenz zwischen den Argumenten von clone() und den Feldern in den an clone3() ubergebenen clone_args: clone() clone3() Hinweise Feld cl_args Schalter & ~0xff flags Fur 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 fur 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 Standardmassig wahlt der Kernel die nachste sequenzielle PID fur den neuen Prozess in jedem der PID-Namensraume, in denen er vorhanden ist. Beim Erstellen eines Prozesses mit clone3() kann das (seit Linux 5.5 verfugbare) Feld set_tid zur Auswahl bestimmter PIDs fur den Prozess in einem oder allen der PID-Namensraume, 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 enthalt) gesetzt werden soll, dann muss das erste Element in dem Feld set_tid auf die gewunschte PID gesetzt werden und set_tid_size muss 1 sein. Falls die PID des neu erstellten Prozesses einen bestimmten Wert in mehreren PID-Namensraumen haben soll, dann kann dass Feld set_tid uber mehrere Eintrage verfugen. Der erste Eintrag definiert die PID im am tiefsten verschachtelten PID-Namensraum und jeder der nachfolgenden Eintrage enthalt die PID in dem entsprechenden Vorfahren-PID-Namensraum. Die Anzahl der PID-Namensraume in denen eine PID gesetzt werden soll, wird mit set_tid_size gesetzt; dieser Wert kann nicht grosser als die Anzahl der derzeit verschachtelten PID-Namensraume sein. Um einen Prozess zu erzeugen, der die nachfolgenden PIDs in einem PID-Namensraum hat: PID-NS-Stufe Angeforderte PID Hinweise 0 31496 Ausserster 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-Namensraumen festgelegt werden mussen, setzen Sie das Feld auf: set_tid[0] = 7; set_tid[1] = 42; set_tid_size = 2; Die PID in den PID-Namensraumen ausserhalb der zwei innersten PID-Namensraume ist genauso wie jede andere PID ausgewahlt. Die Funktionalitat set_tid benotigt CAP_SYS_ADMIN oder (seit Linux 5.9) CAP_CHECKPOINT_RESTORE in allen Benutzernamensraumen, die dem des Ziel-PID-Namensraumes gehoren. Aufrufende durfen in einem gegebenen PID-Namensraum nur eine PID grosser als 1 auswahlen, falls ein init-Prozess (d.h. ein Prozess mit der PID 1) in diesem Namensraum bereits existiert. Andernfalls muss der PID-Eintrag fur diesen PID-Namensraum 1 sein. Die Schaltermaske Sowohl clone() als auch clone3() erlauben eine Schalter-Bit-Maske, die das Verhalten verandert 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() ubergebene 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 aufgefuhrten Konstanten angegeben. Falls nicht unten anders angegeben, sind diese Schalter sowohl in clone() als auch clone3() verfugbar (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<>close-on-exec<< wird bei diesem neuen Dateideskriptor gesetzt. PID-Dateideskriptoren konnen fur die in pidfd_open(2) beschriebenen Zwecke verwandt werden. o Bei der Verwendung von clone3() wird der PID-Dateideskriptor an dem durch cl_args.pidfd angezeigten Ort abgelegt. o Bei der Verwendung von clone() wird der PID-Dateideskriptor an dem Ort abgelegt, auf den Eltern_tid zeigt. Da das Argument Eltern_tid zur Ruckgabe des PID-Dateideskriptors verwandt wird, kann CLONE_PIDFD beim Aufruf von clone() nicht mit CLONE_PARENT_SETTID benutzt werden. Es ist derzeit nicht moglich, 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 zuruckgeliefert. Falls CLONE_DETACHED beim Aufruf von clone3() angegeben wird, wird auch ein Fehler zuruckgeliefert. Dieses Fehlerverhalten stellt sicher, dass das CLONE_DETACHED entsprechende Bit fur weitere PID-Dateideskriptorenfunktionalitaten 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 architekturabhangig. Auf X86 ist tls als ein struct user_desc * interpretiert (siehe set_thread_area(2)). Auf X86-64 ist es der neue fur 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, ausser 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 verandern, 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 konnten Signale durch Aufruf von sigprocmask(2) fur 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. Spatere 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 ausserdem 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 ware) 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 vollstandig entfernt. Seitdem ignoriert der Kernel ihn ohne Fehler. Seit Linux 4.6 wird dasselbe Bit fur 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 uber alle Prozesse, die die Liste gemeinsam nutzen und Semaphore-Anpassungen werden nur durchgefuhrt, wenn der letzte Prozess, der die Liste gemeinsam nutzt, sich beendet (oder mittels unshare(2) aufhort, 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 hinzugefugt wurde, um den POSIX-Thread-Gedanken von einer Thread-Zusammenstellung zu unterstutzen, die sich eine einzelne PID teilt. Intern ist diese gemeinsame PID ein sogenannter Thread-Gruppen-Bezeichner (TGID) fur die Thread-Gruppe. Seit Linux 2.4 geben Aufrufe von getpid(2) die TGID des Aufrufers zuruck. Die Threads innerhalb einer Gruppe konnen durch ihre (systemweit) einheitliche Thread-Kennung (TID) unterschieden werden. Die TID eines neuen Threads ist als Funktionsergebnis verfugbar, das an den Aufrufenden zuruckgegeben 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 Fuhrer 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 fur alle Threads in der Thread-Gruppe zuruckliefern. 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 losgelost 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) durchfuhren, dann werden alle Threads ausser dem Thread-Fuhrer beendet und das neue Programm wird im Thread-Gruppenfuhrer ausgefuhrt. Falls einer der Threads in einer Thread-Gruppe per fork(2) einen Kindprozess erzeugt, dann kann jeder Thread in der Gruppe wait(2) fur diesen Kindprozess ausfuhren. 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 ausgewahlten Thread innerhalb dieser, der das Signal nicht blockiert, ausgeliefert. Ein Signal kann Prozess-orientiert sein, da es vom Kernel aus anderen Grunden (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 ausfuhrte, der eine Hardware-Ausnahmebehandlung ausloste (z.B. lost ein ungultiger Speicherzugriff SIGSEGV oder eine Fliesskommaausnahmebehandlung SIGFPE aus). Ein Aufruf von sigpending(2) liefert eine Signalmenge zuruck, die die Vereinigung der anhangigen Prozess-orientierten Signale und der Signale, die fur den aufrufenden Thread anhangig sind, ist. Falls ein Prozess-orientiertes Signal an eine Thread-Gruppe ausgeliefert wird und die Thread-Gruppe einen Handler fur dieses Signal installiert hat, dann dann wird der Handler in exakt einem willkurlich ausgewahlten 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 willkurlich auswahlen, 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 Ausfuhrung 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 Ausfuhrung 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 Veranderung 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, erhalt der Kindprozess eine eigene Kopie des Speicherbereichs des aufrufenden Prozesses zum Zeitpunkt des Clone-Aufrufs. Fuhrt ein Prozess Schreibzugriffe auf den Speicher oder Anderungen 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. RUCKGABEWERT Bei Erfolg wird im ausgefuhrten Thread des Aufrufenden die Thread-Kennung des Kindprozesses zuruckgegeben. Im Fehlerfall wird im Kontext des Aufrufenden -1 zuruckgegeben, 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) Beschrankungen zum Ablegen des Kindprozesses in die Cgroup der Version 2, auf die sich cl_args.cgroup bezieht, werden nicht erfullt. 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 CLONE_NEWPID und eines (oder beides) von CLONE_THREAD oder CLONE_PARENT wurde in der Schalter-Maske festgelegt. EINVAL In der Schalter-Maske wurden CLONE_NEWUSER und CLONE_THREAD 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() zuruckgegeben, wenn ein Wert von NULL fur 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 fur 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 grosser als die Anzahl der geschachtelten PID-Namensraume. EINVAL (nur clone3()) Eine der in set_tid festgelegten PIDs war ungultig. EINVAL (nur clone3()) CLONE_THREAD oder CLONE_PARENT wurde in der Schalter-Maske festgelegt, aber in exit_signal wurde ein Signal angegeben. EINVAL (nur AArch64, Linux 4.6 und alter) Stapel war nicht an einer 128-Bit-Grenze ausgerichtet. ENOMEM Es kann nicht ausreichend Speicher fur eine Aufgabenstruktur des Kindprozesses reserviert werden oder um benotigte 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-Namensraumen wurde uberschritten; siehe pid_namespaces(7). ENOSPC (seit Linux 4.9; vorher EUSERS) CLONE_NEWUSER wurde in der Schalter-Maske festgelegt und der Aufruf wurde zu einer Uberschreitung der Begrenzung fur die Anzahl von verschachtelten Benutzernamensraumen fuhren. 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 wurde aber die in der enstprechenden Datei in /proc/sys/user festgelegte Begrenzung uberschritten. Fur 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 ungultig 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 fruheren 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 Einhangenamensraums, in dem er sich befindet). EPERM (nur clone3()) set_tid_size war grosser als Null und dem Aufrufenden fehlt in einem oder mehreren Benutzernamensraumen, dem die entsprechenden PID-Namensraume gehoren, 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 wahrend einer Verfolgung sichtbar sein.) EUSERS (Linux 3.11 bis Linux 4.8) CLONE_NEWUSER wurde in der Schalter-Maske festgelegt und die Begrenzung fur die Anzahl von verschachtelten Benutzernamensraumen wurde uberschritten. Siehe die Diskussion des Fehlers ENOSPC oben. VERSIONEN Die Glibc-Wrapperfunktion clone() nimmt einige Anderungen am Speicher vor, auf den Stapel zeigt (Anderungen, um den Stapel korrekt fur das Kind einzurichten), bevor der Systemaufruf clone() ausgelost wird. Verwenden Sie daher in Fallen, in denen clone() zur rekursiven Erstellung von Kindern verwandt wird, nicht den Puffer, der fur den Stapel der Eltern eingesetzt wird, als Stapel der Kinder. 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 Ausfuhrung des Kindprozesses am Zeitpunkt des Aufrufs fortfahrt. 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 erhalt, wenn einer der beiden Prozesse den Stapelspeicher verandert.) 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 uber die Architekturen hinweg Variationen in den Argumenten, wie dies in den folgenden Absatzen dargestellt wird. Die rohe Schnittstelle fur 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 haufigen 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 zusatzliches Argument ubergeben: long clone(unsigned long Schalter, void *Stapel, int Stapelgrosse, /* Grosse des Stapels */ int *Eltern_tid, int *Kind_tid, unsigned long tls); Blackfin, M68k und Sparc Die Konventionen der Argumentubergabe 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 Stapelgrosse, int Schalter, void *arg, /* pid_t *Eltern_tid, struct user_desc *tls, pid_t *Kind_tid */ ); Der oben gezeigte Prototyp ist fur die Glibc-Wrapper-Funktion; fur 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 Stapelgrosse, /* Grosse des Stapels */ int *Eltern_tid, int *Kind_tid, unsigned long tls); __clone2() arbeitet auf die gleiche Weise wie clone(), ausser dass Stapelbasis auf die niedrigste Adresse im Stapelspeicherbereich des Kindprozesses zeigt und Stapelgrosse die Grosse des Stapelspeichers angibt, auf die Stapelbasis zeigt. STANDARDS Linux. GESCHICHTE clone3() Linux 5.3. Linux 2.4 und alter In der Linux 2.4.x-Serie gibt CLONE_THREAD generell dem neuen Prozess nicht den gleichen Elternprozess, wie dem aufrufenden Prozess. Fur 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). Unter Linux 2.4 und fruher gab es die Argumente Eltern_tid, tls und Kind_tid noch nicht. ANMERKUNGEN Diese Systemaufrufe werden benutzt, um Threads zu implementieren: mehrere Steuerflusse in einem Programm, die gleichzeitig in einem gemeinsamen Speicherbereich ausgefuhrt werden. Der Systemaufruf kcmp(2) kann zum Testen, ob zwei Prozesse sich verschiedene Ressourcen, wie die Dateideskriptortabelle, die Rucksetz-Aktionen der System-V-Semaphoren oder einen virtuellen Adressraum, teilen, verwandt werden. Handler, die mittels pthread_atfork(3) registriert sind, werden wahrend eines Clone-Aufrufs nicht ausgefuhrt. FEHLER GNU-C-Bibliotheksversionen 2.3.4 bis einschliesslich 2.24 enthielten eine Wrapper-Funktion fur getpid(2), die Zwischenspeichern von PIDs vornahm. Dieses Zwischenspeichern beruhte auf der Unterstutzung in dem Glibc-Wrapper von clone(), aber Einschrankungen in der Implementierung bedeuteten, dass unter einigen Umstanden 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<<) zuruckgeben, 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 zuruckgeben 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 enthalt.) Um die Wahrheit zu erfahren, war es manchmal notwendig gewesen, Code wie den folgenden zu verwenden: #include 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 Funktionalitat 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 ausgefuhrt wird. Der Kindprozess andert 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 fur die Verwendung dieses Programms finden Sie in setns(2). Innerhalb des Beispielprogramms reservieren wir Speicher, der fur den Stapel des Kindprogramms verwandt werden soll. Dabei verwenden wir aus den folgenden Grunden mmap(2) statt malloc(3): o mmap(2) reserviert einen Speicherblock, der an einer Seitengrenze beginnt und ein Vielfaches der Seitengrosse gross ist. Dies ist nutzlich, um am Ende des Stapels mittels mprotect(2) eine Wachterseite (eine Seite mit dem Schutz PROT_NONE) einzurichten. o Wir konnen den Schalter MAP_STACK angeben, um ein fur den Stapel geeignetes Mapping festzulegen. Derzeit fuhrt dieser Schalter unter Linux zu keiner Aktion, aber er existiert und hat auf anderen Systemen Auswirkungen, daher sollten wir ihn zwecks Portabilitat aufnehmen. Programmquelltext #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include static int /* Funktion fur geklontes Kind starten */ childFunc(void *arg) { struct utsname uts; /* Rechnername im UTS-Namensraum des Kindes andern. */ if (sethostname(arg, strlen(arg)) == -1) err(EXIT_FAILURE, "sethostname"); /* Rechnername ermitteln und anzeigen. */ if (uname(&uts) == -1) err(EXIT_FAILURE, "uname"); printf("uts.nodename in child: %s\n", uts.nodename); /* Mittels >>sleep<< den Namensraum eine Weile offen halten. Dies erlaubt einige Experimente -- beispielsweise konnte ein anderer Prozess den Namensraum betreten. */ sleep(200); return 0; /* Kind wird nun beendet */ } #define STACK_SIZE (1024 * 1024) /* Stapelgrosse fur geklontes Kind */ int main(int argc, char *argv[]) { char *stack; /* Beginn des Stapelpuffers */ char *stackTop; /* Ende des Stapelpuffers */ pid_t pid; struct utsname uts; if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_SUCCESS); } /* Speicher zuweisen, der fur den Stapel des Kindes verwendet wird. */ 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; /* Annehmen, das der Stapel schrumpft */ /* Kind erzeugen, das seinen eigenen UTS-Namensraum hat; Kind beginnt Ausfuhrung in childFunc(). */ pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]); if (pid == -1) err(EXIT_FAILURE, "clone"); printf("clone() returned %jd\n", (intmax_t) pid); /* Elternprozess fallt bis hierher durch */ sleep(1); /* Dem Kind Zeit geben, seinen Rechnernamen zu andern */ /* Rechnernamen im UTS-Namensraum des Elternprozesses anzeigen. Dieser wird sich vom Rechnernamen im UTS-Namensraum des Kindes unterscheiden. */ if (uname(&uts) == -1) err(EXIT_FAILURE, "uname"); printf("uts.nodename in parent: %s\n", uts.nodename); if (waitpid(pid, NULL, 0) == -1) /* Wait for child */ err(EXIT_FAILURE, "waitpid"); printf("child has terminated\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) UBERSETZUNG Die deutsche Ubersetzung dieser Handbuchseite wurde von Daniel Kobras , Chris Leick , Mario Blattermann , Dr. Tobias Quathamer und Helge Kreutzmann erstellt. Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG ubernommen. Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer . Linux man-pages 6.06 1. November 2023 clone(2)