fork(2)

BEZEICHNUNG
fork - erzeugt einen Kindprozess

BIBLIOTHEK
Standard-C-Bibliothek (libc, -lc)

ÜBERSICHT
#include <unistd.h>

pid_t fork(void);

BESCHREIBUNG
fork() erzeugt einen neuen Prozess, indem der aufrufende Prozess dupliziert wird. Der neue Prozess wird als das Kind bezeichnet. Der aufrufende Prozess wird als Elternprozess bezeichnet.

Der Kind- und der Elternprozess laufen in separaten Speicherbereichen. Zum Zeitpunkt von fork() haben beide Speicherbereiche den gleichen Inhalt. Speicherschreibvorgänge, Datei-Mappings (mmap(2)) und Aufhebung von Mappings (munmap(2)) eines Prozesses beeinflussen den jeweiligen anderen Prozess nicht.

Der Kindprozess ist ein exaktes Duplikat des Elternprozesses, mit folgenden Ausnahmen:

•   Das Kind hat seine eigene eindeutige Prozesskennung, die mit keiner Kennung irgendeiner existierenden Prozessgruppe oder Sitzung übereinstimmt (setpgid(2)).

•   Die Elternprozesskennung des Kindes ist die gleiche wie die Prozesskennung des Elternprozesses.

•   Das Kind erbt keine Speichersperren (mlock(2), mlockall(2)) des Elternprozesses.

•   Für das Kind wird die Nutzung von Prozessressourcen (getrusage(2)) und Zähler für CPU-Zeiten (times(2)) auf null zurückgesetzt.

•   Die Menge der für das Kind anstehenden Signale ist anfangs leer (sigpending(2)).

•   Das Kind erbt keine Semaphore-Einstellungen von seinem Elternprozess (semop(2)).

•   Das Kind erbt keine prozess-zugeordneten Datensatzsperren von seinem Elternprozess (fcntl(2)). (Allerdings erbt es offene Dateideskriptionssperren von fcntl(2) und flock(2)-Sperren von seinem Elternprozess.)

•   Das Kind erbt keine Timer von seinem Elternprozess (setitimer(2), alarm(2), timer_create(2)).

•   Das Kind erbt keine ausstehenden asynchronen E/A-Operationen von seinem Elternprozess (aio_read(3), aio_write(3)), auch asynchrone E/A-Kontexte des Elternprozesses werden nicht vererbt (siehe io_setup(2)).

Die Prozessattribute in der vorstehenden Liste werden allesamt in POSIX.1 beschrieben. Eltern- und Kindprozess unterscheiden sich auch in den folgenden Linux-spezifischen Prozessattributen:

•   Das Kind erbt keine Nachrichten über Verzeichnisänderungen (directory change notifications, dnotify) von seinem Elternprozess (siehe die Beschreibung von F_NOTIFY in fcntl(2)).

•   Die Einstellung PR_SET_PDEATHSIG von prctl(2) wird zurückgesetzt, sodass das Kind kein Signal empfängt, wenn sein Elternprozess terminieren.

•   Der voreingestellte Wert für den Timer-Spielraum (»timer slack«) wird auf den aktuellen Timer-Spielraum des Elternprozesses gesetzt. Siehe die Beschreibung von PR_SET_TIMERSLACK in prctl(2).

•   Speicher-Mappings, die mit dem madvise(2)-Schalter MADV_DONTFORK markiert wurden, werden nicht über einen Aufruf von fork() hinweg vererbt.

•   Speicher in dem Adressbereich, der mit dem madvise(2)-Schalter MADV_WIPEONFORK markiert ist, wird nach einem fork() im Kind genullt. (Die Einstellung MADV_WIPEONFORK verbleibt für diese Adressbereiche im Kind.)

•   Das Terminierungssignal des Kindes ist immer SIGCHLD (siehe clone(2)).

•   Die von ioperm(2) gesetzten Bits für Portzugriffe werden nicht an das Kind vererbt, stattdessen muss das Kind benötigte Bits mittels ioperm(2) aktivieren.

Beachten Sie die folgenden weiteren Punkte:

•   Der Kindprozess wird mit einem einzigen Thread erstellt – demjenigen, der fork aufrief. Der gesamte virtuelle Adressraum des Elternprozesses wird im Kind repliziert, einschließlich der Zustände der Mutexe, Zustandsvariablen und anderer »pthread«-Objekte; die Verwendung von pthread_atfork(3) kann für die Behandlung von dadurch verursachten Problemen hilfreich sein.

•   Nach einem fork() in einem Multithread-Programm kann das Kind sicher nur async-signal-safe-Funktionen aufrufen (siehe signal-safety(7)), bis es execve(2) aufruft.

•   Das Kind erbt Kopien der Menge der offenen Dateideskriptoren des Elternprozesses. Jeder Deskriptor des Kindes bezieht sich auf die gleichen offenen Dateideskriptoren (siehe open(2)) wie der entsprechende Dateideskriptor in dem Elternprozess. Dies bedeutet, dass die beiden Dateideskriptoren die Statusschalter geöffneter Dateien, den Datei-Offset und signalgesteuerte E/A-Attribute (siehe die Beschreibung von F_SETOWN und F_SETSIG in fcntl(2)) gemeinsam nutzen.

•   Das Kind erbt Kopien der Menge der Deskriptoren des Elternprozesses für offene Nachrichten-Warteschlangen (siehe mq_overview(7)). Jeder Dateideskriptor des Kindes bezieht sich auf die gleiche Nachrichtenwarteschlangendeskription wie der entsprechende Dateideskriptor in dem Elternprozess. Das bedeutet, dass die beiden Dateideskriptoren die gleichen Schalter (mq_flags) gemeinsam nutzen.

•   Das Kind erbt Kopien der Menge der offenen Verzeichnis-Streams des Elternprozesses (siehe opendir(3)). POSIX.1 besagt, dass die entsprechenden Verzeichnis-Streams auf die gleiche Position zeigen können; unter Linux/Glibc tun sie es nicht.

RÜCKGABEWERT
Bei Erfolg wird im Elternprozess die PID des Kindprozesses zurückgegeben und in dem Kind 0. Bei Fehlern wird dem Elternprozess -1 zurückgegeben, kein Kindprozess erzeugt und errno gesetzt, um den Fehler anzuzeigen.

FEHLER

EAGAIN
    Eine systembedingte Begrenzung der Anzahl der Threads wurde erreicht. Es gibt eine Reihe von Begrenzungen, die diesen Fehler auslösen können:

    •   die weiche Ressourcenbegrenzung RLIMIT_NPROC (mittels setrlimit(2) gesetzt), die die Anzahl der Prozesse und Threads für eine reale Benutzerkennung begrenzt, wurde erreicht;

    •   die systemweite Kernelbegrenzung der Anzahl an Prozessen und Threads, /proc/sys/kernel/threads-max, wurde erreicht (siehe proc(5));

    •   die maximale Anzahl an PIDs, /proc/sys/kernel/pid_max, wurde erreicht (siehe proc(5));

    •   die durch den Cgroup-Controller »process number« erzwungende PID-Begrenzung (pids.max) wurde erreicht.

EAGAIN
    Die aufrufende Instanz agiert gemäß der SCHED_DEADLINE-Scheduling-Regeln und hat den Schalter reset-on-fork nicht gesetzt. Siehe sched(7).

ENOMEM
    fork() konnte wegen Speicherknappheit die erforderlichen Kernel-Strukturen nicht anlegen.

ENOMEM
    Es wurde versucht, einen Kindprozess in einem PID-Namensraum, dessen »init«-Prozess sich beendet hat, zu erstellen. Siehe pid_namespaces(7).

ENOSYS
    fork() wird auf dieser Plattform nicht unterstützt (beispielsweise Hardware ohne eine Speicher-Management-Einheit).

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.)

STANDARDS
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

ANMERKUNGEN
Unter Linux ist fork() mittels »copy-on-write«-Seiten implementiert, sodass der einzige Nachteil von fork() die Zeit und der Speicher ist, der benötigt wird, um die Page Tables des Elternprozesses zu kopieren und eine eindeutige Task-Struktur für das Kind anzulegen.

  Unterschiede C-Bibliothek/Kernel
Der Glibc-Wrapper für fork() wird als Teil der NPTL-Threading-Implementierung bereitgestellt. Seit Version 2.3.3 der Glibc ruft der fork()-Wrapper nicht mehr den Kernel-Systemaufruf fork() auf, sondern clone(2) mit Schaltern, die das Gleiche bewirken wie der traditionelle Systemaufruf. (Ein Aufruf von fork() ist gleichbedeutend mit einem Aufruf von clone(2), bei dem für flags nur SIGCHLD angegeben wird.) Der Glibc-Wrapper ruft alle Fork-Handler auf, die mittels pthread_atfork(3) eingerichtet wurden.

BEISPIELE
Siehe pipe(2) und wait(2) für weitere Beispiele.

    #include <signal.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    int
    main(void)
    {
        pid_t pid;
        if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
            perror("signal");
            exit(EXIT_FAILURE);
        }
        pid = fork();
        switch (pid) {
        case -1:
            perror("fork");
            exit(EXIT_FAILURE);
        case 0:
            puts("Kind beendet sich.");
            exit(EXIT_SUCCESS);
        default:
            printf("Kind ist PID %jd\n", (intmax_t) pid);
            puts("Elternprozess beendet sich.");
            exit(EXIT_SUCCESS);
        }
    }

SIEHE AUCH
clone(2), execve(2), exit(2), setrlimit(2), unshare(2), vfork(2), wait(2), daemon(3), pthread_atfork(3), capabilities(7), credentials(7)

ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Martin Schulze <joey@infodrom.org>, Martin Eberhard Schauer <Martin.E.Schauer@gmx.de>, Holger Wansing <linux@wansing-online.de>, Mario Blättermann <mario.blaettermann@gmail.com> und Helge Kreutzmann <debian@helgefjell.de> erstellt.

Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 (https://www.gnu.org/licenses/gpl-3.0.html) 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 (debian-l10n-german@lists.debian.org).