- あるプロセスの実行中に、別のプロセスを立ち上げるには
fork(2)
を使用する - PHPで
fork(2)
を使用するにはpcntl拡張を使用する - pcntl_forkを使って
fork
を行うことができる
https://github.com/phpsphb/book-examples/blob/master/multiprocess/limited_forking_echo_server.php
<?php
$server = stream_socket_server('tcp://127.0.0.1:'.(getenv('PORT') ?: 1234), $errno, $errstr);
if (false === $server) {
fwrite(STDERR, "Failed creating socket server: $errstr\n");
exit(1);
}
echo "Waiting…\n";
const MAX_PROCS = 2;
$children = [];
for (;;) {
$read = [$server];
$write = null;
$except = null;
stream_select($read, $write, $except, 0, 500);
foreach ($read as $stream) {
if ($stream === $server && count($children) < MAX_PROCS) {
$conn = @stream_socket_accept($server, -1, $peer);
if (!is_resource($conn)) {
continue;
}
echo "Starting a new child process for $peer\n";
$pid = pcntl_fork();
if ($pid > 0) {
$children[] = $pid;
} elseif ($pid === 0) {
// Child process, implement our echo server
$childPid = posix_getpid();
fwrite($conn, "You are connected to process $childPid\n");
while ($buf = fread($conn, 4096)) {
fwrite($conn, $buf);
}
fclose($conn);
// We are done, quit.
exit(0);
}
}
}
// Do housekeeping on exited childs
foreach ($children as $i => $child) {
$result = pcntl_waitpid($child, $status, WNOHANG);
if ($result > 0 && pcntl_wifexited($status)) {
unset($children[$i]);
}
}
echo "\t".count($children)." connected\r";
}
pcntl_fork
の戻り値は、親プロセスの場合は子プロセスのPID、子プロセスの場合は0、fork
に失敗した場合は-1- pcntl_waitpidは終了した子プロセスの プロセス ID を返す
WNOHANG
オプションを指定すると、子プロセスが終了していない場合に直ちに処理を返る
- pcntl_wifexitedはステータスが正常終了したか調べる