php 中的信号处理操作实例详解


Posted in PHP onMarch 04, 2020

本文实例讲述了php 中的信号处理操作。分享给大家供大家参考,具体如下:

首先我们需要了解几个函数

pcntl_signal   安装信号处理器,也就是当指定信号发生时,调用函数。
pcntl_alarm   指定秒数后向进程发送SIGALRM信号。
posix_getpid 返回当前进程id
posix_kill       给指定进程发送信号

一些常用的信号说明

SIGHUP
本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时,
通知同一session内的各个作业, 这时它们与控制终端不再关联。

SIGINT
程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出。

SIGQUIT
和SIGINT类似,但由QUIT字符(通常是Ctrl-/)来控制;进程在因收到SIGQUIT退出时会产生core文件,
在这个意义上类似于一个程序错误信号。

SIGKILL
用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。

SIGTERM
程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,
shell命令kill缺省产生这个信号。如果进程终止不了,我们才会尝试SIGKILL。

SIGUSR1
留给用户使用

SIGUSR2
留给用户使用

SIGALRM
时钟定时信号, 计算的是实际的时间或时钟时间。alarm函数使用该信号。

SIGCHLD
子进程结束时, 父进程会收到这个信号。

例1:

<?php
declare(ticks = 1);
//信号处理函数
function sig_func() {
  echo "child exit \r\n";
}
//设置信号处理器
pcntl_signal(SIGCHLD, 'sig_func');
$pid = pcntl_fork();
if($pid == -1) {
  die('fork error');
} else if ($pid) {
  pcntl_wait($status);
} else {
  echo "child... \r\n";
  exit;
}

当子进程退出时,会向父进程发送SIGCHLD信号,我们通过设置信号处理器,成功的处理信号。

例2:

<?php
declare(ticks = 1);
//信号处理函数
function sig_func($signo) {
  switch($signo) {
    case SIGCHLD: {
      echo "child SIGCHLD \r\n";
      break;
    }
    case SIGTERM: {
      echo "child SIGTERM \r\n";
      break;
    }
    default:
      //处理所有其他信号
      break;
  }
}
//设置信号处理器
pcntl_signal(SIGCHLD, 'sig_func');
//设置信号处理器
pcntl_signal(SIGTERM, 'sig_func');
$pid = pcntl_fork();
if($pid == -1) {
  die('fork error');
} else if ($pid) {
  pcntl_wait($status);
} else {
  sleep(3);
  echo "child \r\n";
  sleep(3);
  posix_kill(getmypid(), SIGTERM);
  exit;
}

父进程等待子进程的退出,子进程等待3秒后输出child,再等待3秒后向自身发送结束程序信号。

例3:

<?php
declare(ticks = 1);
//信号处理函数
function sig_func($signo) {
  switch($signo) {
    case SIGCHLD: {
      echo "child SIGCHLD \r\n";
      break;
    }
    /*这里要把处理SIGTERM信号的代码注释掉
    case SIGTERM: {
      echo "child SIGTERM \r\n";
      break;
    }*/
    default:
      //处理所有其他信号
      break;
  }
}
//设置信号处理器
pcntl_signal(SIGCHLD, 'sig_func');
//设置信号处理器,也注释掉
//不然当父进程发向子进程发送SIGTERM信号时,子进程不会退出,还会继续执行
//我们的信号处理函数把SIGTERM给忽略了
//pcntl_signal(SIGTERM, 'sig_func');
$pid = pcntl_fork();
if($pid == -1) {
  die('fork error');
} else if ($pid) {
  sleep(30);
  posix_kill($pid, SIGTERM);
} else {
  $cnt = 0;
  for(;;) {
    sleep(3);
    echo $cnt, '-';
    ++$cnt;
  }
  exit;
}

父进程在等待30秒后,向子进程发送SIGTERM结束程序信号。如果我们设置了SIGTERM信号的处理器,并且在自定义信号处理器中并没有杀死该进程,则该子进程会一直运行下去。

pcntl_signal()函数仅仅是注册信号和它的处理方法,真正接收到信号并调用其处理方法的是pcntl_signal_dispatch()函数。

例4:

<?php
//使用ticks需要PHP 4.3.0以上版本
//declare(ticks = 1);
function sig_func() {
  echo "SIGALRM \r\n";
}
//设置信号处理器
pcntl_signal(SIGALRM, 'sig_func');
pcntl_alarm(3);

通过函数pcntl_alarm()3秒后给进程发送SIGALRM信号,但信号处理函数并未调用。
原因是我们注释了declare(ticks = 1);这段代码,而又没有调用pcntl_signal_dispatch()函数。

declare(ticks = 1);表示每执行一条低级指令,就检查一次信号,如果检测到注册的信号,就调用其信号处理器。但是这种处理方式效率很低,建议在代码循环中通过pcntl_signal_dispatch()来处理信号。

<?php
//使用ticks需要PHP 4.3.0以上版本
//declare(ticks = 1);
function sig_func() {
  echo "SIGALRM \r\n";
}
//设置信号处理器
pcntl_signal(SIGALRM, 'sig_func');
pcntl_alarm(3);
//因为3秒后pcntl_alarm函数才会给进程发送SIGALRM信号
//所以我们通过sleep函数等待3秒后,调用pcntl_signal_dispatch()来处理信号
sleep(3);
pcntl_signal_dispatch();

pcntl_signal_dispatch()这个函数是PHP5.3以上才支持的,如果你的PHP版本大于5.3,建议使用这个方法调用信号处理器。
5.3以下的版本需要在注册信号之前加上:declare(ticks = 1);

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
简单的用PHP编写的导航条程序
Oct 09 PHP
php面向对象全攻略 (十六) 对象的串行化
Sep 30 PHP
PHP5中新增stdClass 内部保留类
Jun 13 PHP
php和数据库结合的一个简单的web实例 代码分析 (php初学者)
Jul 28 PHP
PHP笔记之:基于面向对象设计的详解
May 14 PHP
destoon设置自定义搜索的方法
Jun 21 PHP
Laravel框架学习笔记(二)项目实战之模型(Models)
Oct 15 PHP
PHP入门教程之图像处理技巧分析
Sep 11 PHP
遍历指定目录,并存储目录内所有文件属性信息的php代码
Oct 28 PHP
基于Laravel实现的用户动态模块开发
Sep 21 PHP
PHP PDOStatement::setFetchMode讲解
Feb 03 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
Apr 04 PHP
php libevent 功能与使用方法详解
Mar 04 #PHP
php+iframe 实现上传文件功能示例
Mar 04 #PHP
php实现文件上传基本验证
Mar 04 #PHP
PHP实现文件上传操作和封装
Mar 04 #PHP
PHP实现文件上传后台处理脚本
Mar 04 #PHP
php 使用html5 XHR2实现上传文件与进度显示功能示例
Mar 03 #PHP
php+ajax实现文件切割上传功能示例
Mar 03 #PHP
You might like
PHP-Fcgi下PHP的执行时间设置方法
2013/08/02 PHP
PHP is_array() 检测变量是否是数组的实现方法
2016/06/13 PHP
javascript 单选框,多选框美化代码
2008/08/01 Javascript
JavaScript 仿关机效果的图片层
2008/12/26 Javascript
javascript中onmouse事件在div中失效问题的解决方法
2012/01/09 Javascript
jQuery往返城市和日期查询实例讲解
2015/10/09 Javascript
JavaScript事件类型中UI事件详解
2016/01/14 Javascript
JS判断指定dom元素是否在屏幕内的方法实例
2017/01/23 Javascript
Vue自定义指令拖拽功能示例
2017/02/17 Javascript
tab栏切换原理
2017/03/22 Javascript
vue基于mint-ui实现城市选择三级联动
2020/06/30 Javascript
JS实现动态生成html table表格的方法分析
2018/07/11 Javascript
小程序组件之自定义顶部导航实例
2019/06/12 Javascript
JS面向对象之单选框实现
2020/01/17 Javascript
详解JavaScript中精度失准问题及解决方法
2020/02/04 Javascript
基于javascript处理二进制图片流过程详解
2020/06/08 Javascript
vue-cli4使用全局less文件中的变量配置操作
2020/10/21 Javascript
[03:39]DOTA2英雄梦之声_第05期_幽鬼
2014/06/23 DOTA
[54:51]Ti4 冒泡赛第二轮LGD vs C9 3
2014/07/14 DOTA
python登录QQ邮箱发信的实现代码
2013/02/10 Python
Python使用MySQLdb for Python操作数据库教程
2014/10/11 Python
在Python中的Django框架中进行字符串翻译
2015/07/27 Python
Python实现全排列的打印
2018/08/18 Python
TensorFlow实现模型评估
2018/09/07 Python
python利用requests库模拟post请求时json的使用教程
2018/12/07 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
一套带答案的C++笔试题
2014/01/10 面试题
早餐连锁店计划书
2014/01/08 职场文书
善意的谎言事例
2014/02/15 职场文书
2014年消防工作实施方案
2014/02/20 职场文书
发展部经理职责规定
2014/02/22 职场文书
闭幕式主持词
2014/04/02 职场文书
超市仓管员岗位职责
2014/04/07 职场文书
意向协议书范本
2014/04/23 职场文书
终止或解除劳动合同及劳动关系的证明书
2014/10/06 职场文书
祝福语集锦:给满月宝宝的祝福语
2019/11/20 职场文书