• PHP 中的多进程使用,进程通信、进程信号等详解


    多进程环境要求

    • Linux 系统
    • php-cli 模式
    • pcntl 扩展 或 swoole 扩展

    pcntl 扩展

    <?php
    $str = "hello world!" . PHP_EOL;
    // 派生一个子进程,子进程会复制主进程中的上下文
    // pcntl_fork 函数在主进程中返回子进程的进程ID,在子进程返回0,失败在主进程返回-1
    $pid = pcntl_fork();
    // 这里开始的代码,会被主进程、子进程共同执行
    echo $str;
    if($pid > 0) {
        echo "我是主进程,子进程的pid是{$pid}" . PHP_EOL;
    } elseif($pid == 0) {
        echo "我是子进程,我的pid是". getmypid() . PHP_EOL;
    }else{
        echo "我是主进程,开启子进程失败" . PHP_EOL;
    }
    

    swoole 扩展

    <?php
    use SwooleProcess;
    $str = "hello world!" . PHP_EOL;
    // 实例化一个进程类
    $process = new Process(function() use($str) {
        echo $str;
        echo "我是子进程,我的pid是" . getmypid() . PHP_EOL;
    });
    // 开启子进程,成功返回子进程的PID,失败返回false
    $pid = $process->start();
    echo $str;
    if($pid > 0){
        $status = Process::wait(true);
        echo "我是主进程,子进程的pid是{$pid}" . PHP_EOL;
    }else{
        echo "我是主进程,开启子进程失败" . PHP_EOL;
    }
    

    进程通信

    通常情况下,各个进程之间的内存空间是相互独立的,不能互相访问。

    在PHP多进程中,pcntl_fork出来的子进程只是复制了父进程的上下文内容,并非共享同一个内存空间,多进程之间无法直接通信。

    进程间通信的几种方式:

    • 管道通信:分为有名管道,无名管道等;
    • 消息队列通信:使用linux的消息队列,需要借助sysvmsg扩展;
    • 进程信号通信;
    • 共享内存通信:映射一段能被其他进程访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问;
    • 套接字通信;
    • 第三方通信:使用文件、mysql、redis等方法实现通信。

    进程信号

    进程信号(Signals)是Unix系统中使用的最古老的进程间通信方法之一。操作系统通过信号来通知进程系统中发生了某种预先规定好的事件,它也是用户进程之间通信和同步的一种原始机制。一个键盘中断或者一个错误条件都有可能产生一个信号。Shell也使用信号向它的子进程发送作业控制信号。

    在一个信号的生命周期中有两个阶段:生成和传送。
    当一个事件发生时,需要通知一个进程,这时就生成了一个信号。
    当进程识别出信号的到来,会采取适当的动作来传送或处理信号。
    在信号到来和进程对信号进行处理之间,信号在进程上挂起(pending)。

    主要的信号源如下:

    • 异常:进程运行过程中出现异常;
    • 其它进程:一个进程可以向另一个或一组进程发送信号;
    • 终端中断:Ctrl-C,Ctrl-等;
    • 作业控制:前台、后台进程的管理;
    • 分配额:CPU超时或文件大小突破限制;
    • 通知:通知进程某事件发生,如I/O就绪等;
    • 报警:计时器到期。

    常见信号

    • SIGHUP: 从终端上发出的结束信号;
    • SIGINT: 来自键盘的中断信号(Ctrl-C);
    • SIGQUIT:来自键盘的退出信号(Ctrl-);
    • SIGFPE: 浮点异常信号(例如浮点运算溢出);
    • SIGKILL:结束接收此信号的进程;
    • SIGALRM:进程的定时器到期时,发送该信号;
    • SIGTERM:kill 命令发出的信号;
    • SIGCHLD:标识子进程停止运行或已运行结束的信号;

    信号缺省动作

    • 异常终止(abort):在进程的当前目录下,把进程的地址空间内容、寄存器内容保存到一个叫做core的文件中,然后终止进程。
    • 退出(exit):不产生core文件,直接终止进程。
    • 忽略(ignore):忽略该信号。
    • 停止(stop):挂起该进程。
    • 继续(continue):如果进程被挂起,则恢复进程的运行。否则,忽略信号。

    进程可以对信号所采取的操作

    • 忽略信号:进程可忽略产生的信号,但 SIGKILL 和 SIGSTOP 信号不能被忽略,必须处理(由进程自己或由内核处理)。进程可以忽略掉系统产生的大多数信号。
    • 阻塞信号:进程可选择阻塞某些信号,即先将到来的某些信号记录下来,等到以后(解除阻塞后)再处理它。
    • 由进程处理该信号:进程本身可在系统中注册处理信号的处理程序地址,当发出该信号时,由注册的处理程序处理信号。
    • 由内核进行缺省处理:信号由内核的缺省处理程序处理,执行该信号的缺省动作。例如,进程接收到SIGFPE(浮点异常)的缺省动作是产生core并退出。大多数情况下,信号由内核处理。

    信号没有固有的优先级。如果为一个进程同时产生了两个信号,这两个信号会以任意顺序出现在进程中并会按任意顺序被处理。另外,也没有机制用于区分同一种类的多个信号。如果进程在处理某个信号之前,又有相同的信号发出,则进程只能接收到一个信号。进程无法知道它接收了一个还是多个SIGCONT信号。

  • 相关阅读:
    最新国家标准下载(2020-7-31)
    SL/T 264-2020 水利水电工程岩石试验规程
    SH/T 3082-2019 石油化工仪表供电设计规范
    GB/T 4780-2020 汽车车身术语
    Java——冒泡排序
    JSP处理XML数据
    JSP标准标签库(JSTL)
    千锤百炼软工第十九天
    千锤百炼软工第十八天
    千锤百炼软工第十七天
  • 原文地址:https://www.cnblogs.com/danhuang/p/12924094.html
Copyright © 2020-2023  润新知