Start · Sprachen · PHP · Referenz · pcntl_forkx

pcntl_forkx

Funktion

Erzeugt einen Kindprozess mittels <code>forkx(2)</code> und ermöglicht dabei die Übergabe von Flags zur Steuerung des Fork-Verhaltens.

seit PHP 8.3.0 Kategorie: misc

Signatur

pcntl_forkx(int $flags): int

Beschreibung

pcntl_forkx() ist eine erweiterte Variante von pcntl_fork() und nutzt den systemnahen Aufruf forkx(2) (verfügbar auf Solaris/illumos-basierten Systemen). Die Funktion erstellt eine exakte Kopie des aktuellen Prozesses als Kindprozess. Über den Parameter flags lässt sich das Verhalten des Fork-Vorgangs genauer steuern – beispielsweise ob der Kindprozess mit einem sauberen Adressraum gestartet wird.

Der Rückgabewert unterscheidet sich je nach Kontext: Im Elternprozess wird die PID des Kindprozesses zurückgegeben, im Kindprozess selbst wird 0 zurückgegeben. Bei einem Fehler gibt die Funktion -1 zurück und es wird kein Kindprozess erzeugt.

Diese Funktion steht nur auf Betriebssystemen zur Verfügung, die forkx(2) implementieren (hauptsächlich Solaris und darauf basierende Systeme wie OmniOS oder SmartOS). Auf Linux oder macOS ist pcntl_fork() die passende Alternative.

Wie bei allen PCNTL-Funktionen muss die Erweiterung pcntl aktiviert sein, und der Einsatz ist typischerweise auf CLI-Skripte beschränkt, da das Forking in Webserver-Umgebungen zu unvorhersehbarem Verhalten führen kann.

Parameter

Name Typ Default Beschreibung
$flags Pflicht int Flags zur Steuerung des Fork-Verhaltens. Gültige Werte sind systemabhängig und entsprechen den Konstanten des forkx(2)-Systemaufrufs, z. B. FORK_NOSIGCHLD oder FORK_WAITPID. Auf nicht unterstützten Systemen hat dieser Parameter keine Wirkung bzw. führt zu einem Fehler.

Rückgabewert

Typ
int
Beschreibung
Gibt im Elternprozess die PID (Prozess-ID) des erzeugten Kindprozesses zurück. Im Kindprozess selbst wird 0 zurückgegeben. Bei einem Fehler wird -1 zurückgegeben und kein Kindprozess erstellt.

Beispiele

Einfaches Forking mit pcntl_forkx

<?php
$pid = pcntl_forkx(FORK_NOSIGCHLD);

if ($pid === -1) {
    // Fehler beim Forken
    die('Fehler: Kindprozess konnte nicht erzeugt werden.');
} elseif ($pid === 0) {
    // Wir befinden uns im Kindprozess
    echo "Kindprozess: PID = " . posix_getpid() . PHP_EOL;
    exit(0);
} else {
    // Wir befinden uns im Elternprozess
    echo "Elternprozess: Kindprozess-PID = $pid" . PHP_EOL;
    // Auf den Kindprozess warten
    pcntl_waitpid($pid, $status);
    echo "Elternprozess: Kindprozess beendet mit Status " . pcntl_wexitstatus($status) . PHP_EOL;
}
Elternprozess: Kindprozess-PID = 12345 Kindprozess: PID = 12345 Elternprozess: Kindprozess beendet mit Status 0

Parallele Verarbeitung mit mehreren Kindprozessen

<?php
$numWorkers = 3;
$children = [];

for ($i = 0; $i < $numWorkers; $i++) {
    $pid = pcntl_forkx(FORK_NOSIGCHLD);
    if ($pid === -1) {
        die("Fehler beim Erzeugen des Kindprozesses $i");
    } elseif ($pid === 0) {
        // Kindprozess: Aufgabe verarbeiten
        echo "Worker $i (PID: " . posix_getpid() . ") startet Aufgabe." . PHP_EOL;
        sleep(1); // Simuliert eine Aufgabe
        echo "Worker $i abgeschlossen." . PHP_EOL;
        exit(0);
    } else {
        // Elternprozess: PID des Kindes merken
        $children[] = $pid;
    }
}

// Elternprozess wartet auf alle Kinder
foreach ($children as $childPid) {
    pcntl_waitpid($childPid, $status);
    echo "Kind PID $childPid beendet." . PHP_EOL;
}

echo "Alle Worker abgeschlossen." . PHP_EOL;
Worker 0 (PID: 1001) startet Aufgabe. Worker 1 (PID: 1002) startet Aufgabe. Worker 2 (PID: 1003) startet Aufgabe. Worker 0 abgeschlossen. Worker 1 abgeschlossen. Worker 2 abgeschlossen. Kind PID 1001 beendet. Kind PID 1002 beendet. Kind PID 1003 beendet. Alle Worker abgeschlossen.

// Wichtig · Fallstricke

Plattformabhängigkeit: pcntl_forkx() ist nur auf Systemen verfügbar, die den Systemaufruf forkx(2) unterstützen (hauptsächlich Solaris und abgeleitete Systeme). Auf Linux und macOS sollte stattdessen pcntl_fork() verwendet werden. Der Versuch, die Funktion auf einem nicht unterstützten System aufzurufen, kann zu einem Fatal Error führen.

Zombie-Prozesse vermeiden: Kindprozesse, auf die der Elternprozess nicht wartet, werden zu Zombie-Prozessen. Verwende immer pcntl_waitpid() oder installiere einen Signal-Handler mit pcntl_signal(SIGCHLD, SIG_IGN), um dies zu verhindern.

Webserver-Umgebungen: Der Einsatz von pcntl_forkx() in Webserver-Umgebungen (z. B. Apache, PHP-FPM) ist gefährlich und nicht empfohlen, da es zu inkonsistenten Zuständen bei geteilten Ressourcen wie Datenbankverbindungen führen kann. Diese Funktion sollte ausschließlich in CLI-Skripten genutzt werden.

Ressourcen im Kindprozess: Nach dem Fork teilen Eltern- und Kindprozess zunächst Ressourcen (Copy-on-Write). Offene Datenbankverbindungen oder Sockets sollten im Kindprozess neu aufgebaut werden, um Konflikte zu vermeiden.