用脑思考,用心琢磨,用行动证实 [登录·注册]

吕滔博客

首页 开发 运维 工具 摄影

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个
  • 发布文章:1534篇
  • 用户评论:751条
  • 开博至今:4127天

正则速查

[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 只匹配最近的一个字符串;不重复匹配

最新回复

  • hyvm.net: 好文章,点赞
  • 新闻头条: 文章不错非常喜欢
  • 志志: 折腾了半天 感谢大神
  • Smithk464: Hey very nice blog!! Man .. Exce...
  • memory: 我已投奔phpstrom.哈哈
  • 逆风飘扬: 原来是这样!!!!!!!用惯了VS的来用zend studio没...
  • NS: 请问我这么写之后抛出了一个 javax.crypto.BadPa...
  • memory: 有内部使用的,开源的过段时间放个出来。
  • 小小: 博主 ,可有写好的
  • 111: 我看不懂唉,好多内容
  • memory: 咧,难道我手误了,回头看下官方文档去...
  • 阿东: 进入镜像的 后面 /bin/bash 是错的 你应该用的是/b...
  • memory: 帝国的安全性来说,比phpcms和dede要好的多啦.
  • 西点师培训班: 现在帝国用的少了,开源的不太会改,老被黑
  • yiyiyizoe: 谢谢~
  • memory: 不好意思呀,这个也是13年的时候,安装过淘宝的这个开源系统,做的...
  • yiyiyizoe: 实在抱歉,如果可以回答的话,只需要看这个问题:ldb支持批量导入...