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 相关文章推荐
Search Engine Friendly的URL设计
Oct 09 PHP
PHP中文汉字验证码
Apr 08 PHP
php读取30天之内的根据算法排序的代码
Apr 06 PHP
我的php学习笔记(毕业设计)
Feb 21 PHP
关于访问控制的一首PHP面试题(对属性或方法的访问控制)
Sep 13 PHP
php获取通过http协议post提交过来xml数据及解析xml
Dec 16 PHP
PHP延迟静态绑定示例分享
Jun 22 PHP
php返回字符串中所有单词的方法
Mar 09 PHP
PHP脚本监控Nginx 502错误并自动重启php-fpm
May 13 PHP
php使用PDO从数据库表中读取数据的实现方法(必看)
Jun 02 PHP
php写入txt乱码的解决方法
Sep 17 PHP
php 使用expat方式解析xml文件操作示例
Nov 26 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
关于时间计算的结总
2006/12/06 PHP
PHP会员找回密码功能的简单实现
2016/09/05 PHP
js获取元素在浏览器中的绝对位置
2010/07/24 Javascript
JS中 用户登录系统的解决办法
2013/04/15 Javascript
window.open()详解及浏览器兼容性问题示例探讨
2014/05/29 Javascript
node.js中的http.response.addTrailers方法使用说明
2014/12/14 Javascript
在JavaScript中处理字符串之link()方法的使用
2015/06/08 Javascript
js显示当前日期时间和星期几
2015/10/22 Javascript
浅谈JavaScript对象与继承
2016/07/10 Javascript
jQuery实现两个select控件的互移操作
2016/12/22 Javascript
利用Js+Css实现折纸动态导航效果实例源码
2017/01/25 Javascript
移动端触屏幻灯片图片切换插件idangerous swiper.js
2017/04/10 Javascript
vue事件修饰符和按键修饰符用法总结
2017/07/25 Javascript
vuejs使用FormData实现ajax上传图片文件
2017/08/08 Javascript
js移动端事件基础及常用事件库详解
2017/08/15 Javascript
Vue filter介绍及其使用详解
2017/10/21 Javascript
JS 遍历 json 和 JQuery 遍历json操作完整示例
2019/11/11 jQuery
深入分析JavaScript 事件循环(Event Loop)
2020/06/19 Javascript
[03:37]2014DOTA2国际邀请赛 主赛事第一日胜者组TOPPLAY
2014/07/19 DOTA
[01:26]神话结束了,却也刚刚开始——DOTA2新英雄玛尔斯驾临战场
2019/03/10 DOTA
Python闭包的两个注意事项(推荐)
2017/03/20 Python
Python之自动获取公网IP的实例讲解
2017/10/01 Python
一百多行python代码实现抢票助手
2018/09/25 Python
python实现把两个二维array叠加成三维array示例
2019/11/29 Python
pytorch:实现简单的GAN示例(MNIST数据集)
2020/01/10 Python
python同义词替换的实现(jieba分词)
2020/01/21 Python
Python计算公交发车时间的完整代码
2020/02/12 Python
Python编程快速上手——正则表达式查找功能案例分析
2020/02/28 Python
CSS3等相关属性制作分页导航实现代码
2012/12/24 HTML / CSS
英国领先的酒类网上商城:TheDrinkShop
2017/03/16 全球购物
美国户外运动商店:Sun & Ski
2018/08/23 全球购物
美国最好的葡萄酒网上商店:Wine Library
2019/11/02 全球购物
市场拓展计划书
2014/05/03 职场文书
2015年仓管员工作总结
2015/04/21 职场文书
2015秋季田径运动会广播稿
2015/08/19 职场文书
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android