Start · Sprachen · PHP · Referenz · pcntl_rfork

pcntl_rfork

Funktion

Erstellt einen neuen Prozess oder Thread und ermöglicht die gezielte Steuerung, welche Ressourcen zwischen Eltern- und Kindprozess geteilt oder getrennt werden.

seit PHP 7.4.0 Kategorie: misc

Signatur

pcntl_rfork(int $flags, int $signal = 0): int

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

Typ
int
Beschreibung
Gibt im Elternprozess die PID des Kindprozesses zurück, im Kindprozess 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;
}
Elternprozess: Kindprozess hat PID 12345 Kindprozess PID: 12345 Kindprozess beendet.

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;
}
Kindprozess gestartet mit PID: 12346 Ich bin der Kindprozess.

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