PHP Socket Programming Handbook 読書メモ PHPによるマルチプロセスプログラミング

php_socket_programming_handbook


  • あるプロセスの実行中に、別のプロセスを立ち上げるには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はステータスが正常終了したか調べる

コメントをどうぞ

コメントを残す