Signatur
Beschreibung
pcntl_rfork() ist eine BSD-spezifische Erweiterung des klassischen fork()-Systemaufrufs, die es erlaubt, über Flags präzise zu kontrollieren, welche Prozessressourcen (z. B. Dateizeigerraum, Signalbehandlung, Speicher) zwischen dem Elternprozess und dem neu erstellten Prozess geteilt werden. Die Funktion steht nur auf Systemen zur Verfügung, die den nativen rfork(2)-Systemaufruf unterstützen (primär FreeBSD, NetBSD, DragonFly BSD).
Über den Parameter flags können Kombinationen aus vordefinierten Konstanten wie RFPROC, RFMEM, RFFDG, RFNOWAIT u. a. übergeben werden, um das Verhalten des neuen Prozesses zu definieren. Damit ist eine deutlich feinere Kontrolle möglich als mit dem einfachen pcntl_fork().
Der Rückgabewert verhält sich ähnlich wie bei fork(): Im Elternprozess wird die PID des Kindprozesses zurückgegeben, im Kindprozess 0, bei einem Fehler -1. Der optionale Parameter signal gibt das Signal an, das an den Elternprozess gesendet wird, wenn der Kindprozess endet (wird nur bei bestimmten Flags ausgewertet).
Da pcntl_rfork() plattformabhängig ist und nur unter bestimmten BSD-Systemen verfügbar ist, sollte die Verfügbarkeit via function_exists() geprüft werden. Für portable Unix/Linux-Anwendungen ist pcntl_fork() die bevorzugte Alternative.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $flags Pflicht | int | Bitmaske aus RF*-Konstanten (z. B. RFPROC, RFMEM, RFFDG, RFNOWAIT), die festlegen, welche Ressourcen zwischen Eltern- und Kindprozess geteilt oder kopiert werden. |
|
| $signal | int | 0 | Signal-Nummer, die an den Elternprozess gesendet wird, wenn der Kindprozess terminiert. Wird nur in Kombination mit bestimmten Flags (z. B. RFTSIGZMB) ausgewertet. Der Standardwert 0 bedeutet kein Signal. |
Rückgabewert
0. Bei einem Fehler wird -1 zurückgegeben.Beispiele
Einfacher rfork-Aufruf mit RFPROC und RFFDG
<?php
if (!function_exists('pcntl_rfork')) {
echo 'pcntl_rfork ist auf diesem System nicht verfügbar.' . PHP_EOL;
exit(1);
}
// RFPROC erstellt neuen Prozess, RFFDG kopiert den Dateideskriptor-Raum
$pid = pcntl_rfork(RFPROC | RFFDG);
if ($pid === -1) {
die('Fehler beim Aufruf von pcntl_rfork');
} elseif ($pid === 0) {
// Kindprozess
echo 'Kindprozess PID: ' . getmypid() . PHP_EOL;
exit(0);
} else {
// Elternprozess
echo 'Elternprozess: Kindprozess hat PID ' . $pid . PHP_EOL;
pcntl_wait($status);
echo 'Kindprozess beendet.' . PHP_EOL;
}
Verfügbarkeitsprüfung und Fallback auf pcntl_fork
<?php
function fork_prozess(): int {
if (function_exists('pcntl_rfork')) {
// BSD: Feingranulare Kontrolle
return pcntl_rfork(RFPROC | RFFDG | RFNOWAIT);
} elseif (function_exists('pcntl_fork')) {
// Linux/portabler Fallback
return pcntl_fork();
}
throw new RuntimeException('Kein fork-Mechanismus verfügbar.');
}
$pid = fork_prozess();
if ($pid === -1) {
die('Fork fehlgeschlagen.');
} elseif ($pid === 0) {
echo 'Ich bin der Kindprozess.' . PHP_EOL;
exit(0);
} else {
echo 'Kindprozess gestartet mit PID: ' . $pid . PHP_EOL;
}
// Wichtig · Fallstricke
Plattformabhängigkeit: pcntl_rfork() ist ausschließlich auf BSD-basierten Systemen verfügbar (FreeBSD, NetBSD, DragonFly BSD). Unter Linux ist die Funktion nicht verfügbar. PHP muss außerdem mit aktivierter PCNTL-Erweiterung kompiliert worden sein.
Konstanten: Die verfügbaren RF*-Konstanten (wie RFPROC, RFMEM, RFFDG, RFNOWAIT, RFCFDG) sind ebenfalls nur auf BSD-Systemen definiert. Der Einsatz ohne vorherige Prüfung via defined() kann zu Fehlern führen.
Zombie-Prozesse: Ohne RFNOWAIT muss der Elternprozess den Kindprozess via pcntl_wait() oder pcntl_waitpid() abholen, um Zombie-Prozesse zu vermeiden.
Sicherheit: Wie bei allen Fork-basierten Mechanismen sollten Ressourcen (Datenbankverbindungen, Datei-Handles) nach dem Fork sorgfältig verwaltet werden, da geteilte Ressourcen zu Race Conditions und Datenverlust führen können.