Signatur
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
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;
}
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;
// 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.