Swoole的多进程模块

介绍

Swoole是有自己的一个进程管理模块,用来替代PHP的pcntl扩展,需要注意Process进程在系统是非常昂贵的资源,创建进程消耗很大,另外创建的进程过多会导致进程切换开销大幅上升

僵尸进程和孤儿进程的区别

  1. 僵尸进程:一个子进程在父进程还没有调用wait()方法或者waitpid()方法的情况下退出,这个子进程就是僵尸进程;

  2. 孤儿进程:一个父进程退出,它的一个或多个子进程还在运行,子进程将成为孤儿进程,孤儿进程将被init进程所收养;

  3. 僵尸进程将会导致资源浪费,而孤儿进程则不会。

一、定义
什么是僵尸进程
维基百科的定义:在类UNIX系统中,僵尸进程是指完成执行(通过exit系统调用,或运行时发生致命错误或收到终止信号所致)但在操作系统的进程表中仍然有一个表项(进程控制块PCB),处于”终止状态”的进程。

这个定义很准确,但并不好理解,通俗的说法是一个进程fork了一个子进程,子进程先于父进程退出,但父进程没有调用wait(通过wait系统调用读取退出进程的退出态,退出进程的在进程表中的表项就被删除),导致这个进程已经退出但是仍在进程表中占有一个位置,这种进程称为僵尸进程。

什么是孤儿进程
孤儿进程:一个进程fork了一个子进程, 父进程先于子进程退出,运行中的子进程称为孤儿进程。
孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

下面,让我们来看2个示例:僵尸进程

echo 'ppid = ' . getmypid(), PHP_EOL;
 $process = new swoole_process(function (swoole_process $worker) {
    echo 'pid = ' . getmypid(), PHP_EOL;
    sleep(10);
    echo 'child process exit', PHP_EOL;
}, false);
 
$process->start();
 
sleep(1000);
echo 'parent process exit', PHP_EOL;
#子进程在父进程没有执行完就退出了,所以会产生僵尸进程
#一般流程是子进程在父进程执行完wait后再退出,

 孤儿进程

echo 'ppid = ' . getmypid(), PHP_EOL;
$process = new swoole_process(function (swoole_process $worker) {
    echo 'pid = ' . getmypid(), PHP_EOL;
    sleep(1000);
    echo 'child process exit', PHP_EOL;
}, false);
$process->start();
sleep(10);
echo 'parent process exit', PHP_EOL;

为什么不使用pcntl

  1. pcntl没有提供进程间通信的功能
  2. pcntl不支持重定向标准输入和输出
  3. pcntl只提供了fork这样原始的接口,容易使用错误

Swoole是怎么解决的

    1. swoole_process提供了基于unixsock的进程间通信,使用很简单只需调用write/read或者push/pop即可
    2. swoole_process支持重定向标准输入和输出,在子进程内echo不会打印屏幕,而是写入管道,读键盘输入可以重定向为管道读取数据
    3. swoole_process提供了exec接口,创建的进程可以执行其他程序,与原PHP父进程之间可以方便的通

创建进程

SwooleProcess::__construct(callable $function, $redirect_stdin_stdout = false, $create_pipe = true)

  $function,子进程创建成功后要执行的函数,底层会自动将函数保存到对象的callback属性上。如果希望更改执行的函数,可赋值新的函数到对象的callback属性

  $redirect_stdin_stdout,重定向子进程的标准输入和输出。启用此选项后,在子进程内输出内容将不是打印屏幕,而是写入到主进程管道。读取键盘输入将变为从管道中读取数据。默认为阻塞读取。

  $create_pipe,是否创建管道,启用$redirect_stdin_stdout后,此选项将忽略用户参数,强制为true。如果子进程内没有进程间通信,可以设置为 false。

<?php
for ($i = 0; $i < 6; $i++) {#创建了3个子进程
    $process = new SwooleProcess(function ($process) {
        echo PHP_EOL . posix_getpid() . PHP_EOL;
    }, false, false);
    $process->start();
}
swoole_process::wait();//等待防止出现僵尸进程
?>

 

原文地址:https://www.cnblogs.com/zh718594493/p/12251630.html