`
Jonathan樊
  • 浏览: 74603 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

Linux下PHP多进程实现(1)

阅读更多

什么是一个进程?

进程这个概念是针对系统而不是针对用户的,对用户来说,他面对的概念是程序。当用户敲入命令执行一个程序的时候,对系统而言,它将启动一个进程。但和程序不同的是,在这个进程中,系统可能需要再启动一个或多个进程来完成独立的多个任务。多进程编程的主要内容包括进程控制和进程间通信,在了解这些之前,我们先要简单知道进程的结构。

 

Linux下进程的结构

Linux下一个进程在内存里有三部分的数据:"代码段"、"堆栈段"和"数据段"。"代码段",顾名思义,就是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。"堆栈段"存放的就是子程序的返回地址、子程序的参数以及程序的局部变量。而数据段则存放程序的全局变量,常数以及动态数据分配的数据空间。

 

Linux下进程控制

在传统的Unix环境下,有两个基本的操作用于创建和修改进程:函数fork( )用来创建一个新的进程,该进程几乎是当前进程的一个完全拷贝;函数族exec( )用来启动另外的进程以取代当前运行的进程。

fork()之后exec()之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。

 

fork()函数一次调用却有两个返回值。对于父进程,fork()函数返回了子程序的进程号,而对于子程序,fork()函数则返回零。如果函数调用不成功,则返回-1。

 

在进程运行时,如果子进程先退出,它不会从进程列表里清除。而要发一个SIGCHLD(或SIGCLD)信号给父进程,父进程确认后子进程才会退出。在等待父进程确认期间,子进程处于“zombie”状态。所以我们就需要使用wait()函数。如果调用wait()函数时已经有一个处于“zombie”状态的子进程,那么函数立即返回的同时该子进程从内存中清除出去;否则,主进程会处于阻塞状态,直到子进程退出后才继续执行,而无法进行其他任务。还有一个办法可以解决办法就是拦截处理信号SIGCHLD(或SIGCLD)。子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD, SIG_IGN) 通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收, 并不再给父进程发送信号。

 

在Linux系统中,子进程的正常/异常终止都会给父进程发送SIGCHLD的信号,当父进程接收到子进程(第一个)信号进行wait()或waitpid()时,会屏蔽掉下一个的SIGCHLD信号,实际的效果就是在信号处理函数返回前不会重入。

那么当父进程在执行信号处理函数时,又有子进程(第二个)退出,那么信号会被阻塞并等待处理,假如(第三个)又来了,那么它是被抛弃的,后续的都会抛弃。。。

所以说信号是阻塞但不排队的。

如果子进程可能会同时退出,那么父进程需要这样来处理以防止僵尸进程的出现:

while( (childpid = waitpid(-1, NULL, WNOHANG)) > 0)

{

 ...

}

这样,即使出现子进程同时退出的情况,SIGCHLD的信号被抛弃也没有关系。waitpid会收集所有当前已终止(实际就是处于僵尸状态)的子进程,直到没有这样的进程状态需要收集(返回0)。

 

一个简单的例子如下:

<?php
/**
 * 多进程实现
 * User: Eleanor
 * Date: 2014/12/23
 * Time: 18:49
 */
declare(ticks = 1);
define('ProcessNum',5);
function signalHandler($signal){
    if($signal==SIGCHLD){
        echo 'SIGCHLD received.'."\n";
    }
    //$pid = pcntl_wait($status, WNOHANG);
    $pid = pcntl_waitpid(-1, $status, WNOHANG);
    echo "{$pid} exit; \n";
}
pcntl_signal(SIGCHLD,"signalHandler",true);
//pcntl_signal_dispatch();
for($i=0;$i<ProcessNum;$i++){
    $pid=pcntl_fork();
    if($pid==-1){
        exit("create child process failed \n");
    }elseif($pid==0){
        echo "I am the child process. my pid is:".posix_getpid().'and my parent pid is:'.posix_getppid()."\n";
        exit ;
    }
}
while(1){
    echo "Waiting for child process to finish... \n";
    sleep(1);
}

 

 

<?php
/**
 * 多进程实现
 * User: Eleanor
 * Date: 2014/12/23
 * Time: 18:49
 */
declare(ticks = 1);
define('ProcessNum',10);
function signalHandler($signal){
    if($signal==SIGCHLD){
        echo 'SIGCHLD received.'."\n";
    }
}
pcntl_signal(SIGCHLD,"signalHandler");
//pcntl_signal_dispatch();

for($i=0;$i<ProcessNum;$i++){
    $pid=pcntl_fork();
    if($pid==-1){
        exit("create child process failed \n");
    }elseif($pid==0){
        echo "I am the child process. my pid is:".posix_getpid().'and my parent pid is:'.posix_getppid()."\n";
        exit ;
    }
}

while(($pid = pcntl_wait($status)) > 0)
{
    echo "{$pid} exit; \n";
}

 

 执行结果如下:


 

 

  • 大小: 228.3 KB
  • 大小: 230 KB
1
1
分享到:
评论

相关推荐

    PHP多进程编程实例

    主要介绍了PHP多进程编程实例,本文讲解的是在Linux下实现PHP多进程编程,需要的朋友可以参考下

    Linux下实现PHP多进程的方法分享

    PHP多进程:使用PHP的Process Control Functions... 以下为实现PHP多进程的简单测试代码: 复制代码 代码如下: &lt;?php declare(ticks=1); $bWaitFlag = FALSE; /// 是否等待进程结束 $intNum = 10; /// 进程总数 $

    taskPHP基于php开发的定时计划任务框架,多进程实现任务的分配和运行

    taskPHP基于php开发的定时计划任务框架,多进程实现任务的分配和运行,支持多进程和多线程模式需要安装pthreads扩展(可选),支持linux和windows。

    PHP多进程编程实例详解

    主要介绍了PHP多进程编程方法,较为详细的分析了PHP多进程编程的概念、用法、相关函数与使用技巧,需要的朋友可以参考下

    PHP多进程编程总结(推荐)

    1. 准备 在动手之前,请确定你用的不是M$ Windows平台(因为我没有Windows)。Linux / BSD / Unix应该都是没问题的。确认好了工作环境以后一起来看看我们需要的PHP模块是否都有。打开终端输入下面的命令: $ php -m ...

    浅析PHP7的多进程及实例

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

    PHP常驻内存的多进程任务管理器Composer包

    PHP常驻内存的多进程任务管理器Composer包。以进程管理为出发点,同时也支持为每个进程设置定时执行功能,您可以用它来完成需要重复运行的任务(如订单超时自动取消,短信邮件异步推送,队列/消费者/频道订阅者等等),...

    php开启多进程的方法

    本文实例讲述了php开启多进程的方法。分享给大家供大家参考。具体实现方法如下: 复制代码 代码如下: &lt;?php  $IP=’192.168.1.1′;//Windows電腦的IP  $Port=’5900′; //VNC使用的Port  $ServerPort=’9999...

    解决Linux下php-fpm进程过多导致内存耗尽问题

    最近,发现个人博客的Linux服务器,数据库服务经常挂掉,导致需要重启,才能正常访问,极其恶心,于是决心开始解决问题,解放我的时间和精力(我可不想经常出问题,然后人工重启,费力费时)。 分析问题 发现问题...

    PHP使用pcntl_fork实现多进程下载图片的方法

    注意:PHP有个pcntl_fork的函数可以实现多进程,但要加载pcntl拓展,而且只有在linux下才能编译这个拓展. 1.首先在ubuntu下编译pcntl.so,我的ubuntu下找不到pcntl的包,于是创建一个文件夹下载了整个PHP包,在里面找

    PHP 多进程与信号中断实现多任务常驻内存管理实例方法

    本文章基于 pcntl 扩展做的多进程测试。 进程调度策略 父子进程的调度由操作系统来负责,具体先调度子进程还是父进程由系统的调度算法决定,当然可以在父进程加上延时或是调用进程回收函数 pcntl_wait 可以先让子...

    LINUX网站建设技术指南

    第1章 了解Linux及其网络结构 1.1 Linux简介 1.1.1 何谓Linux 1.1.2 Linux的功能 1.1.3 Linux当前的版本 1.2 Linux的TCP/IP网络结构 1.3 IPv6简介 1.3.1 IPv6与IPv4头标的比较 1.3.2 简化的头标 1.3.3 参数的修订 ...

    Linux C程序设计大全

    第1篇 Linux下C语言基础 第1章 Linux简介 1.1 GNU简介 1.2 Linux简介 1.2.1 Linux发展史 1.2.2 Linux发行版 1.2.3 Linux内核版本 1.2.4 Linux与UNIX的关系 1.2.5 Linux在服务器方面的发展 1.2.6 Linux在嵌入式系统...

    taskPHP--基于php开发的定时计划任务框架.zip

    建议生产部署在linux下运行多进程模式,因为运行在多线程模式运行一段时间后报错,pthreads has detected that the core\lib\Pthread could not be started, the system lacks the necessary resources or the system...

    PHP下操作Linux消息队列完成进程间通信的方法

    当我们开发的系统需要使用多进程方式运行时,进程间通信便成了至关重要的环节。消息队列(message queue)是Linux系统进程间通信的一种方式。

    php的POSIX 函数以及进程测试的深入分析

    复制代码 代码如下:&lt;?... //8805sleep(10);... 您可能感兴趣的文章:深入解析PHP中的(伪)多线程与多进程PHP多进程编程实例深入探究PHP的多进程编程方法PHP下操作Linux消息队列完成进程间通信的方法PH

    基于PHP-FPM进程池探秘

    PHP 支持多进程而不支持多线程;PHP-FPM 在进程池中运行多个子进程并发处理所有连接请求。通过 ps 查看PHP-FPM进程池(pm.start_servers = 2)状态如下: root@d856fd02d2fe:~# ps aux -L USER PID LWP %CPU NLWP %...

    什么是PHP7中的孤儿进程与僵尸进程

    我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工作终止...

Global site tag (gtag.js) - Google Analytics