Signatur
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";
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']]);
}
}
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);
// 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.