찾다
php教程php手册初探PHP多进程

准备

我们都知道PHP是单进程执行的,PHP处理多并发主要是依赖服务器或PHP-FPM的多进程及它们进程的复用,但PHP实现多进程也意义重大,尤其是在后台Cli模式下处理大量数据或运行后台DEMON守护进程时,多进程的优势不用多说。

PHP的多线程也曾被人提及,但进程内多线程资源共享和分配的问题难以解决。PHP也有多线程想关的扩展 pthreads ,但据说不太稳定,且要求环境为线程安全,所用不多。

以前PHP群里的一位大神曾指导说后台PHP想进阶必然避不开多进程,正好公司里的守护进程也应用了PHP的多进程,结合着谷哥的各种资料和手册,总算理解了多进程,并自己写了一个小demo(在linux系统上实现的),用此文总结一下,如有错漏,谢谢提出。

要实现PHP的多进程,我们需要两个扩展 pcntl和 posix,安装方法这里不再赘述。


创建子进程

创建PHP子进程是多进程的开始,我们需要pcntl_fork()函数;

fork函数详解

pcntl_fork() — 在当前进程当前位置产生分支(子进程)。此函数创建了一个新的子进程后,子进程会继承父进程当前的上下文,和父进程一样从pcntl_fork()函数处继续向下执行,只是获取到的pcntl_fork()的返回值不同,我们便能从判断返回值来区分父进程和子进程,分配父进程和子进程去做不同的逻辑处理。

pcntl_fork()函数成功执行时会在父进程返回子进程的进程id(pid),因为系统的初始进程init进程的pid为1,后来产生进程的pid都会大于此进程,所以我们可以通过判断pcntl_fork()的返回值大于1来确实当前进程是父进程;

而在子进程中,此函数的返回值会是固定值0,我们也可以通过判断pcntl_fork()的返回值为0来确定子进程;

而pcntl_fork()函数在执行失败时,会在父进程返回-1,当然也不会有子进程产生。

fork进程实例

以下是fork子进程的一个简单的小例子:

    $ppid = posix_getpid();
    $pid = pcntl_fork();
    if ($pid == -1) {
        throw new Exception('fork子进程失败!');
    } elseif ($pid > 0) {
        cli_set_process_title("我是父进程,我的进程id是{$ppid}.");<br />     sleep(30); // 保持30秒,确保能被ps查到
    } else {
        $cpid = posix_getpid();
        cli_set_process_title("我是{$ppid}的子进程,我的进程id是{$cpid}.");
        sleep(30);
    }

这时介绍一下两个函数:

posix_getpid():获取当前进程的pid;

cli_set_process_title('响亮的名字'):为当前进程取一个响亮的名字。

运行这个例子,我们便能看到当前两个PHP进程了。 


管理子进程

创建好了进程,那么怎么对子进程进行管理呢?使用信号。

在计算机科学中,信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。

分发信号处理器

我们通过在父进程接收子进程传来的信号,判断子进程状态,来对子进程进行管理。

我们需要在父进程里使用pcntl_signal()函数和pcntl_signal_dispatch()函数来给各个子进程安装信号处理器。

pcntl_signal (int $signo , callback $handler) 安装一个信号处理器;
        $signo是待处理的信号常量,callback是其处理函数

pcntl_signal_dispatch () 调用每个等待信号通过pcntl_signal()安装的处理器

PHP内常见的信号常量有:

        SIGCHLD     子进程退出成为僵尸进程会向父进程发送此信号
        SIGHUP      进程挂起
        SIGTEM      进程终止
        ...         // 其他请在手册中查看

安装并调用信号处理器后,一旦子进程有相应的信号返回给父进程,父进程就可以调用相应的callback函数对子进程处理;

处理子进程

对子进程的处理方法有:

posix_kill():此函数并不能顾名思义,它通过向子进程发送一个信号来操作子进程,在需要要时可以选择给子进程发送进程终止信号来终止子进程;

pcntl_waitpid():等待或返回fork的子进程状态,如果指定的子进程在此函数调用时已经退出(俗称僵尸进程),此函数将立刻返回,并释放子进程的所有系统资源,此进程可以避免子进程变成僵尸进程,造成系统资源浪费;

下面是两个函数的函数原型:

bool posix_kill ( int $pid , int $sig ) // 向进程id为$pid的进程发送$sig信号,$sig常见信号如上;

int pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] )  // 挂起当前进程的执行直到进程号为$pid的进程退出(如果$pid为-1,则等待任意一个子进程); 

总结

这就是PHP多进程的基础使用了,感兴趣的可以自己写一个demo试一试手了。

最后贴一下鸟哥所说的PHP多进程优点:

  1. 使用多进程, 子进程结束以后, 内核会负责回收资源
  2. 使用多进程,子进程异常退出不会导致整个进程Thread退出. 父进程还有机会重建流程.
  3. 一个常驻主进程, 只负责任务分发, 逻辑更清楚.

对了,还有一个实例,改日上传到github,欢迎大家关注 >> 枕边书。

参考资料:

PHP CLI模式下的多进程应用 - 风雪之隅

PHP多进程编程初步-PureWeber - 纯粹互联网

用php编写守护进程 - 胡超博客

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구