比别人多一点志气,你就会多一份出息 [登录·注册]

吕滔博客

首页 开发 运维 工具 摄影

PHP多进程之pcntl扩展的使用详解

开发 memory 发布于May 17, 2017 标签: PHP

安装

1.编译php源码时加入

--enable-pcntl

2.在现有的环境下新增加扩展

cd php-version/ext/pcntl  
phpize  
./configure && make && make install  
echo "extension=pcntl.so" >> /etc/php.ini  

3.Mac下用brew安装 例如我本地是php7.1.5

brew install php71-pcntl 

使用

header('content-type:text/html;charset=utf-8' );  
  
// 必须加载扩展  
if (!function_exists("pcntl_fork")) {  
    die("pcntl extention is must !");  
} 
pcntl_signal(SIGCHLD, SIG_IGN); //如果父进程不关心子进程什么时候结束,子进程结束后,内核会回收。  
$pid_dir = __dir__."/pid_files";
for($i=0; $i<3; $i++){
    $pid = pcntl_fork(); //创建子进程 
    if($pid == -1){
        //错误处理:创建子进程失败时返回-1.
        var_dump("fork failed");
    }
    if(!$pid){
        //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。  
        //子进程代码
        $pid = posix_getpid();
        $ppid = posix_getppid();
        $r = rand(0,100);  //随机数
        touch("$pid_dir/fork_child_process_{$i}_{$ppid}_{$pid}_{$r}");
        exit;
    }else{
        //父进程会得到子进程号,所以这里是父进程执行的逻辑  
        //如果不需要阻塞进程,而又想得到子进程的退出状态,则可以注释掉pcntl_wait($status)语句,或写成:  
        pcntl_wait($status,WNOHANG); //等待子进程中断,防止子进程成为僵尸进程。
    }
} 
$pid = posix_getpid();
$ppid = posix_getppid();
$r = rand(0,100); //随机数
touch("$pid_dir/fork_process_pid_{$ppid}_{$pid}_$r");

相关参数

pcntl_waitpid

等待或返回fork的子进程状态。
多进程的主进程创建了子进程,那主进程如何确认子进程的状态呢。 假如主进程需要根据子进程的状态做不同的处理呢, 这里的状态包括子进程被kill掉,或变成僵尸进程等。 pcntl_waitpid就可以获取子进程的状态码, 通过这个状态码, 就可知道子进程处于什么状态
他的用法:

int pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] )

返回的值可以是-1,0或者 >0的值, 如果是-1, 表示子进程出错, 如果>0表示子进程已经退出且值是退出的子进程pid,至于如何退出, 可以通过$status状态码反应。 那什么时候返回0呢, 只有在option 参数为 WNOHANG且子进程正在运行时0, 也就是说当设置了options=WNOHANG时, 如果子进程还没有退出, 此时pcntl_waitpid就会返回0
另外, 如果不设置这个参数为WNOHANG, pcntl_waitpid 就会阻塞运行, 直到子进程退出, 至于option的另外一个值WUNTRACED, 暂未理解, 不表

那么如何根据$status(状态码)判断进程是如何退出呢, 如下(参数都是$status)

pcntl_wifexited

这个函数可以根据$status 判断进程是否正常退出, 何为正常退出, 比如exit

pcntl_wexitstatus

这个函数仅在pcntl_wifexited 返回True(即正常退出)时有效, 且返回子进程退出的返回状态码, 这个返回状态码可以通过exit($s)的参数($s必须为整数时)定义

pcntl_wifsignaled

检查子进程状态码是否代表由于某个信号而中断, 比如是不是我们给他发送了term, int 等信号了

pcntl_wexitstatus

假如是发送信号而导致子进程中断, 那么这个信号是什么信号呢, 这个函数就是获取这个信号的

pcntl_wifstopped

仅当option选项为WUNTRACED时有效, 未理解, 不表

pcntl_wtermsig

同上

综合实例代码:

$res = pcntl_waitpid($pid, $status, WNOHANG);
//FileLog::log("pid is $pid; wait result is $res");
if($res == -1 || $res > 0){
    if(!pcntl_wifexited($status)){
        //进程非正常退出
        FileLog::log("service stop unusally; pid is $pid");
    }else{
        //获取进程终端的退出状态码;
        $code = pcntl_wexitstatus($status);
        FileLog::log("service stop code: $code;pid is $pid ");
    }

    if(pcntl_wifsignaled($status)){
        //不是通过接受信号中断
        FileLog::log("service stop not by signal;pid is $pid ");
    }else{
        $signal = pcntl_wtermsig($status);
        FileLog::log("service stop by signal $signal;pid is $pid");
    }
}

上面的这个代码就通过根据pcntl_waitpid的返回结果和状态码对子进程因为不同原因中断做了不同的处理

官方文档:http://php.net/manual/zh/book.pcntl.php

相关推荐

添加新评论

全部评论:已有 2 条评论

  1. 香港服务器

    很详细,学习了

  2. 上海代理记账

    看起来代码有一些复杂的呀。。。

网站状态

  • 栏目分类:49个
  • 发布文章:1313篇
  • 用户评论:690条
  • 开博至今:3979天

正则速查

[abc] 匹配中括号中的单个字符,如a或b或c
[^abc] 匹配除了a、b、c等字符的其他单个字符
[a-z] 匹配一个字符范围,如a到z
[a-zA-Z] 匹配一个字符范围,如a-z 或 A-Z
^ 匹配行的开始
$ 匹配行的结束
\A 匹配一个字符串的开始
\z 匹配一个字符串的结束
. 匹配任意单个字符
\s 匹配空白字符,如空格,TAB
\S 匹配非空白字符
\d 匹配一个数字
\D 匹配非数字
\w 匹配一个字母
\W 匹配非字母
\b 匹配字符边界
(...) 引用所有括号中的内容
(a|b) a或者b
a? 零个或1个a
a* 零个或多个a
a+ 1个或多个a
a{3} 3次重复的a
a{3,} 3次或3次以上重复的a
a{3,6} 3到6次重复的a

修正符

/g 查找所有可能的匹配
/i 不区分大小写
/m 多行匹配
/s 单行匹配
/x 忽略空白模式
/e 可执行模式,PHP专有
/A 强制从目标字符串开头匹配
/D 使用$限制结尾字符,则不允许结尾有换行
/U 只匹配最近的一个字符串;不重复匹配

最新回复

  • pengcheng: 已解决
  • pengcheng: Oops! It seems that sphinx was b...
  • 券都有: 感谢分享
  • memory: 这是我3年前玩过一次,当时因为安装完后,发现日常办公还好,但是好...
  • sdf: 想问一下,激活工具激活后,后面会出现提示要再次重新激活吗?
  • memory: 你要用碗装我吗?还是要我把扔的扔进你碗里???!!! &^_^&
  • 薛才杰: 同感,快扔到我的碗里来。。。
  • memory: 要说明一下,在大陆及香港的云主机或VPS,都是不支持的。原因都懂...
  • 历史趣谈LishiQtan: 很好的文章,值得收藏
  • memory: 现在回头看,,,这么烂的代码,也是醉了.
  • memory: 有空试试apache的
  • 脚踏实地: rInfo数组是怎么来的
  • 朋友们: 我都是这么建站的
  • memory: 明眼人.
  • 上官元恒: $lunarInfo数组是怎么来的,这是重点
  • memory: 你知道的太多了...
  • yjl: 这个肯定解决的不是空间的问题,可能是复用的问题,有可能是“站群”的问题