• Process::__construct
    • 创建子进程
    • 管道类型
    • 在子进程中创建 Server
    • IO 线程池问题

    Process::__construct

    创建子进程

    1. swoole_process::__construct(callable $function, bool $redirect_stdin_stdout = false,
    2. int $pipe_type = 2, bool $enable_coroutine = false);
    • $function,子进程创建成功后要执行的函数,底层会自动将函数保存到对象的callback属性上。如果希望更改执行的函数,可赋值新的函数到对象的callback属性
    • $redirect_stdin_stdout,重定向子进程的标准输入和输出。启用此选项后,在子进程内输出内容将不是打印屏幕,而是写入到主进程管道。读取键盘输入将变为从管道中读取数据。默认为阻塞读取。
    • $pipe_type,管道类型,启用$redirect_stdin_stdout后,此选项将忽略用户参数,强制为1。如果子进程内没有进程间通信,可以设置为 0
    • $enable_coroutine,默认为false,在callback function中启用协程,开启后可以直接在子进程的函数中使用协程API
    $enable_coroutine4.3.0或更高版本可用

    管道类型

    • 0:不创建管道
    • 1:创建SOCK_STREAM类型管道
    • 2:创建SOCK_DGRAM类型管道
    • 启用$redirect_stdin_stdout 后,此选项将忽略用户参数,强制为1
    Process 对象在销毁时会自动关闭管道,子进程内如果监听了管道会收到CLOSE事件 使用Process作为监控父进程,创建管理子进程时,父类必须注册信号SIGCHLD对退出的进程执行wait,否则子进程退出时会变成僵尸进程

    在子进程中创建 Server

    例 1:

    可以在 swoole_process 创建的子进程中使用 swoole_server,但为了安全必须在$process->start 创建进程后,调用 $worker->exec() 执行。代码如下:

    1. <?php
    2. $process = new swoole_process('callback_function', true);
    3. $pid = $process->start();
    4. function callback_function(swoole_process $worker)
    5. {
    6. $worker->exec('/usr/local/bin/php', array(__DIR__.'/swoole_server.php'));
    7. }
    8. swoole_process::wait();

    例 2:使用匿名函数作为进程逻辑,并实现了一个简单的父子进程通讯

    1. <?php
    2. $process = new swoole_process(function (swoole_process $process) {
    3. $process->write('Hello');
    4. }, true);
    5. $process->start();
    6. usleep(100);
    7. echo $process->read(); // 输出 Hello

    IO 线程池问题

    由于Swoole的异步文件IO使用了线程池,在使用了这些API之后再创建Process可能会出现非常复杂的带线程fork问题。因此请勿在使用异步文件IO函数后创建Process

    2.1.4/1.10.4或更高版本已经禁止了这种行为,底层检测到已创建线程池再执行new Process会抛出致命错误