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 相关文章推荐
php4的session功能评述(二)
Oct 09 PHP
php下连接mssql2005的代码
Jan 17 PHP
ajax 的post方法实例(带循环)
Jul 04 PHP
解析用PHP读写音频文件信息的详解(支持WMA和MP3)
May 10 PHP
使用CodeIgniter的类库做图片上传
Jun 12 PHP
完整删除ecshop中获取店铺信息的API
Dec 24 PHP
smarty模板引擎之分配数据类型
Mar 30 PHP
PHP数组与对象之间使用递归实现转换的方法
Jun 24 PHP
php根据年月获取当月天数及日期数组的方法
Nov 30 PHP
详解Yaf框架PHPUnit集成测试方法
Dec 27 PHP
PHP实现从上往下打印二叉树的方法
Jan 18 PHP
Laravel + Elasticsearch 实现中文搜索的方法
Feb 02 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 查找字符串常用函数介绍
2012/06/07 PHP
PHP获取数组最后一个值的2种方法
2015/01/21 PHP
PHP 中 Orientation 属性判断上传图片是否需要旋转
2015/10/16 PHP
JavaScript 小型打飞机游戏实现原理说明
2010/10/28 Javascript
通过百度地图获取公交线路的站点坐标的js代码
2012/05/11 Javascript
JQuery调webservice实现邮箱验证(检测是否可用)
2013/05/21 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
2015/12/03 Javascript
jQuery中实现prop()函数控制多选框(全选,反选)
2016/08/19 Javascript
Javascript中 带名 匿名 箭头函数的重要区别(推荐)
2017/01/29 Javascript
jQuery插件HighCharts绘制2D金字塔图效果示例【附demo源码下载】
2017/03/09 Javascript
Angular中实现树形结构视图实例代码
2017/05/05 Javascript
Vue 表单控件绑定的实现示例
2017/08/11 Javascript
Vue.directive()的用法和实例详解
2018/03/04 Javascript
axios拦截设置和错误处理方法
2018/03/05 Javascript
vue中如何去掉空格的方法实现
2018/11/09 Javascript
如何在微信小程序中存setStorage
2019/12/13 Javascript
微信小程序跨页面传递data数据方法解析
2019/12/13 Javascript
如何在VUE中使用vue-awesome-swiper
2021/01/04 Vue.js
实例讲解python函数式编程
2014/06/09 Python
在Windows服务器下用Apache和mod_wsgi配置Python应用的教程
2015/05/06 Python
python转换字符串为摩尔斯电码的方法
2015/07/06 Python
Python基于百度AI的文字识别的示例
2018/04/21 Python
python 筛选数据集中列中value长度大于20的数据集方法
2018/06/14 Python
python删除字符串中指定字符的方法
2018/08/13 Python
django 微信网页授权登陆的实现
2019/07/30 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
2020/03/09 Python
Python利用Faiss库实现ANN近邻搜索的方法详解
2020/08/03 Python
通过HTML5规范搞定i、em、b、strong元素的区别
2017/03/04 HTML / CSS
利用Storage Event实现页面间通信的示例代码
2018/07/26 HTML / CSS
Html5在手机端调用相机的方法实现
2020/05/13 HTML / CSS
用JAVA SOCKET编程,读服务器几个字符,再写入本地显示
2012/11/25 面试题
小学生元旦感言
2014/02/26 职场文书
关于教师节的演讲稿
2014/09/04 职场文书
2014年祖国生日寄语
2014/09/19 职场文书
工伤事故赔偿协议书
2015/08/06 职场文书
Redis命令处理过程源码解析
2022/02/12 Redis