Start · Sprachen · PHP · Referenz · Swoole\Process

Swoole\Process

Klasse

Erstellt und verwaltet Kindprozesse sowie die Interprozesskommunikation (IPC) zwischen Eltern- und Kindprozessen in Swoole.

seit PHP 1.7.2 Kategorie: misc

Signatur

class Swoole\Process

Beschreibung

Swoole\Process ist eine objektorientierte Abstraktion zur Prozessverwaltung in PHP, die auf den POSIX-Systemaufrufen fork(), exec() und verwandten IPC-Mechanismen basiert. Sie ermöglicht es, Hintergrundprozesse, Worker-Pools und nebenläufige Aufgaben ohne klassische PHP-Extensions wie pcntl direkt aus dem Swoole-Ökosystem heraus zu erstellen.

Ein Kindprozess wird durch die Übergabe einer Callback-Funktion an den Konstruktor definiert. Die Ausführung erfolgt nach dem Aufruf von start(). Eltern- und Kindprozess können über eine integrierte Unix-Socket-Pipe (write()/read()) oder über Swoole-eigene Nachrichtenwarteschlangen (push()/pop()) miteinander kommunizieren.

Typische Einsatzbereiche sind lang laufende Worker-Prozesse in eigenen Daemon-Services, die Parallelisierung von CPU-intensiven Aufgaben sowie die Implementierung von Multi-Process-Architekturen außerhalb eines HTTP-Server-Kontexts. Wichtig ist, dass beendete Kindprozesse via Swoole\Process::wait() im Elternprozess "recycled" werden müssen, um Zombie-Prozesse zu vermeiden.

Die Klasse steht nur in der Swoole-Extension zur Verfügung und ist daher ausschließlich in einer Umgebung nutzbar, in der Swoole installiert und geladen ist. Die Verwendung in einem laufenden Swoole-HTTP- oder TCP-Server erfordert besondere Vorsicht, da forked Prozesse bestehende Event-Loop-Zustände erben.

Parameter

Name Typ Default Beschreibung
$callback Pflicht callable Die Callback-Funktion, die im Kindprozess ausgeführt wird. Sie erhält das Swoole\Process-Objekt als erstes Argument.
$redirect_stdin_stdout bool false Wenn true, werden stdin und stdout des Kindprozesses auf die Pipe umgeleitet, sodass Ausgaben des Kindprozesses über read() vom Elternprozess gelesen werden können.
$pipe_type int 1 Gibt den Typ der erzeugten Pipe an: 0 = keine Pipe, 1 = SOCK_STREAM (Standard), 2 = SOCK_DGRAM. Beeinflusst die IPC-Kommunikationsart zwischen Eltern- und Kindprozess.
$enable_coroutine bool false Wenn true, wird im Kindprozess automatisch eine Coroutine-Umgebung (Event-Loop) gestartet, sodass der Callback als Coroutine ausgeführt werden kann.

Beispiele

Einfacher Kindprozess mit Pipe-Kommunikation

<?php
// Kindprozess erstellen: sendet eine Nachricht an den Elternprozess
$process = new Swoole\Process(function (Swoole\Process $worker) {
    // Kindprozess: Nachricht an den Elternprozess schreiben
    $worker->write('Hallo vom Kindprozess!');
    // Kindprozess beendet sich nach dem Callback automatisch
}, false, 1);

// Prozess starten (fork)
$pid = $process->start();
echo "Kindprozess gestartet mit PID: {$pid}\n";

// Elternprozess liest Nachricht vom Kindprozess
$message = $process->read();
echo "Empfangene Nachricht: {$message}\n";

// Kindprozess recyclen, um Zombie-Prozesse zu vermeiden
$result = Swoole\Process::wait(true);
echo "Kindprozess beendet, PID: {$result['pid']}, Exit-Code: {$result['code']}\n";
Kindprozess gestartet mit PID: 12345 Empfangene Nachricht: Hallo vom Kindprozess! Kindprozess beendet, PID: 12345, Exit-Code: 0

Worker-Pool: Mehrere Kindprozesse parallel starten

<?php
$workers = [];
$workerCount = 4;

for ($i = 0; $i < $workerCount; $i++) {
    $process = new Swoole\Process(function (Swoole\Process $worker) use ($i) {
        // Simulierte Arbeit im Kindprozess
        echo "Worker #{$i} (PID: " . posix_getpid() . ") startet Arbeit...\n";
        sleep(1); // CPU-intensive oder I/O-Aufgabe
        echo "Worker #{$i} fertig.\n";
    });

    $pid = $process->start();
    $workers[$pid] = $process;
    echo "Worker #{$i} gestartet mit PID: {$pid}\n";
}

// Auf alle Kindprozesse warten
while (!empty($workers)) {
    $result = Swoole\Process::wait(true); // blockierend
    if ($result) {
        echo "Worker mit PID {$result['pid']} beendet (Exit-Code: {$result['code']}).\n";
        unset($workers[$result['pid']]);
    }
}
Worker #0 gestartet mit PID: 12346 Worker #1 gestartet mit PID: 12347 Worker #2 gestartet mit PID: 12348 Worker #3 gestartet mit PID: 12349 Worker #0 (PID: 12346) startet Arbeit... ...

Kindprozess mit exec() – externes Programm ausführen

<?php
$process = new Swoole\Process(function (Swoole\Process $worker) {
    // Externes Programm im Kindprozess starten (ersetzt den Prozess-Image)
    $worker->exec('/usr/bin/php', ['-r', 'echo "PHP aus exec()\n";']);
}, true); // redirect_stdin_stdout = true

$process->start();

// Ausgabe des externen Prozesses lesen
$output = $process->read();
echo "Ausgabe: {$output}";

Swoole\Process::wait(true);
Ausgabe: PHP aus exec()

// Wichtig · Fallstricke

Zombie-Prozesse: Jeder gestartete Kindprozess muss nach seiner Beendigung mit Swoole\Process::wait() im Elternprozess "recycled" werden. Geschieht dies nicht, verbleibt der Prozess als Zombie in der Prozesstabelle und verbraucht Systemressourcen.

Vorsicht im Server-Kontext: Wird Swoole\Process innerhalb eines laufenden Swoole\Server- oder Swoole\Http\Server-Callbacks genutzt, erbt der geforkte Kindprozess den gesamten Speicher und den Event-Loop-Zustand des Servers. Dies kann zu undefiniertem Verhalten führen. Stattdessen sollte $server->addProcess() verwendet werden.

Coroutine-Kontext: Mit enable_coroutine = true kann im Kindprozess ein vollständiger Coroutine-Scheduler genutzt werden. Ohne diese Option sind Swoole-Coroutine-APIs im Kindprozess nicht verfügbar.

Signalbehandlung: Die statische Methode Swoole\Process::signal() sollte verwendet werden, um SIGCHLD-Signale abzufangen und wait() asynchron aufzurufen, wenn ein nicht-blockierender Workflow benötigt wird.