PHP进程简述

php中的进程是以扩展的形式来完成。通过这些扩展,我们能够很轻松的完成进程的一系列动作。

pcntl扩展:主要的进程扩展,完成进程创建于等待操作。。

  •     构建此扩展不需要其他扩展。
  •     在PHP中进程控制支持默认是关闭的。您需要使用 --enable-pcntl 配置选项重新编译PHP的 CGI或CLI版本以打开进程控制支持。
  •     此扩展没有在 php.ini 中定义配置指令。
  •     此扩展没有定义资源类型。

  • 当前,这个模块没有非Unix平台可用的函数(即非Unix类系统不支持此模块)。

     

posix扩展:完成posix兼容机通用api,如获取进程id,杀死进程等。

  •     构建此扩展不需要其他扩展。
  •     POSIX functions are enabled by default. You can disable POSIX-like functions with --disable-posix .
  •     此扩展没有在 php.ini 中定义配置指令。
  •     此扩展没有定义资源类型。


关于fork后的执行顺序:

<?php
function aa(){
    echo 'AA_start';
    bb();
    echo 'AA_end';
}
function bb(){
    echo 'BB_start';
    $pid = pcntl_fork();
    if ($pid == 0) {
        echo 'son';
        return;            //此处是return 
    } elseif ($pid > 0) {
        echo 'parent'
    }
    pcntl_waitpid($pid , $status, 0); //等待子进程结束
    echo 'BB_end';
}
aa();
/*
AA_start
BB_start
parent
son
AA_end
BB_end        //父进程被阻塞了 要等子进程执行完才会继续 所以父进程最后输出
AA_end
*/
// BB_end只输出了一次;AA_END输出了两次,也是说fork子进程,子进程的后续代码是完全遵循父进程的代码顺序的;此时就需要将return更改为exit 直接关闭就可以了

 象下面代码可以直接return:

<?php
$sons = [
    'son_a' => 1,
    'son_b' => 2,
    'son_c' => 3,
    'son_d' => 4,
];
$pids = [];
foreach ($sons as $k => $v) {
    $pids[$k] = pcntl_fork();   //1.为当前进程创建一个子进程,并且先运行父进程,返回的是子进程的PID;子/父进程都从此处开始执行
    if ($pids[$k] == 0 ) {      //2.父级先到达此处 跳转到2.1;子进程后到达 跳转到3处
        $pid = posix_getpid();  //3。子进程进来
        echo $k.'_'.$pid.PHP_EOL;
        sonOut($v);
        return;                 //4.在子进程的代码块中最好有exit/return语句,即执行完子进程后立即就结束。否则它也会执行 第一步中的创建进程
    } elseif ($pids[$k] > 0) {  //2.1 先执行父级代码代码
        echo $k."_parent:".posix_getpid().PHP_EOL;
    }
}

function sonOut($v) {
    for ($i=1; $i <= $v; $i++){
        echo $v.'_'.'_'.$i.PHP_EOL;
        if($v == 4){
            echo PHP_EOL;
        }
        sleep(1);
    }
    
}
$status = '';
foreach ($pids as $pid) {
    $res = pcntl_waitpid($pid, $status,0);//在父进程的代码中用 pcntl_waitpid($pid,&$status)阻塞父进程直到他的子进程有返回值
    echo $res.'_'.$status.PHP_EOL;
}
exit('end');

 


[root@iZbp1hs2rode8m3mzs1jjpZ public]# php pcntl.php
son_a_parent:7972
son_a_7973
1__1
son_b_parent:7972
son_b_7974
2__1
son_c_parent:7972
son_d_parent:7972
son_c_7975
3__1
son_d_7976
4__1

2__2
3__2
4__2

7973_0
3__3
4__3

7974_0
4__4

7975_0
7976_0

进程信号:

pcntl_signal — 安装一个信号处理器
       pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] ) : bool
pcntl_signal_dispatch — 调用每个等待信号通过pcntl_signal() 安装的处理器。
       pcntl_signal_dispatch ( void ) : bool  

pcntl_signal的实现原理是,触发信号后先将信号加入一个队列中。
然后在PHP的ticks回调函数中不断检查是否有信号,
如果有信号就执行PHP中指定的回调函数,如果没有则跳出函数。
 
ticks=1表示每执行1行PHP代码就回调此函数。
实际上大部分时间都没有信号产生,但ticks的函数一直会执行。 

比较好的做法是去掉ticks,转而使用pcntl_signal_dispatch,在代码循环中自行处理信号。

比较两段代码

第一段

<?php
//使用ticks需要PHP 4.3.0以上版本
declare(ticks = 1);

echo microtime(true)."安装信号处理器...\n";
pcntl_signal(SIGHUP,  function($signo) {
     echo microtime(true)."信号处理器被调用\n";
});

echo "为自己生成SIGHUP信号...\n";
posix_kill(posix_getpid(), SIGHUP);

echo "分发...\n";
pcntl_signal_dispatch();

echo "完成\n";

 

[root@iZbp1hs2rode8m3mzs1jjpZ public]# php api.php
1585023396.5262_安装信号处理器...
为自己生成SIGHUP信号...
1585023396.5263_信号处理器被调用
分发...
完成

第二段

<?php
echo microtime(true)."_安装信号处理器...\n";
pcntl_signal(SIGHUP,  function($signo) {
     echo microtime(true)."_信号处理器被调用\n";
});

echo "为自己生成SIGHUP信号...\n";
posix_kill(posix_getpid(), SIGHUP);
sleep(3);
echo "分发...\n";
pcntl_signal_dispatch();

echo "完成\n";
1585023348.3601_安装信号处理器...
为自己生成SIGHUP信号...
分发...
1585023351.3603_信号处理器被调用
完成

仔细看信号调用的时间戳 使用declare(ticks = 1); 创建信号时候 立即就调用了;如果去掉declare(ticks = 1); 改用pcntl_signal_dispatch则在pcntl_signal_dispatch调用后执行调用函数

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值