IT培训-高端面授IT培训机构
云和教育:云和数据集团高端IT职业教育品牌 全国咨询热线:0371-67988003
课程 请选择课程
    校区 请选择校区
      • 华为
        授权培训中心
      • 腾讯云
        一级认证培训中心
      • 百度营销大学
        豫陕深授权运营中心
      • Oracle甲骨文
        OAEP中心
      • Microsoft Azure
        微软云合作伙伴
      • Unity公司
        战略合作伙伴
      • 普华基础软件
        战略合作伙伴
      • 新开普(股票代码300248)
        旗下丹诚开普投资
      • 中国互联网百强企业锐之旗
        旗下锐旗资本投资

      PHP如何优雅的处理信号?看完这篇文章你就知道了!

      • 发布时间:
        2019-08-01
      • 版权所有:
        云和教育
      • 分享:

      PHP进程间通信的另外一个手段就是通过信号来在进程间传递信息。信号是一种系统调用,通常我们用的kill命令就是发送某个信号给某个进程的。

      在开发服务器端守护进程方面,信号处理至关重要。PHP的pcntl扩展提供了信号处理的功能,利用它可以让PHP来接管信号的处理。

      配图1 PHP如何优雅的处理信号.jpg

      今天,我们就来给大家讲一讲PHP中的信号处理。

      什么是信号?

      信号是事件发生时对进程的通知机制,有时又称为软件中断。一个进程可以向另一个进程发送信号,比如子进程结束时都会向父进程发送一个SIGCHLD(17号信号)来通知父进程,所以有时信号也被当作一种进程间通信的机制。

      信号的产生是有多种方式的,下面是常见的几种:

      ●键盘上按某些组合键,比如Ctrl+C或者Ctrl+D等,会产生SIGINT信号。

      ●使用posix kill调用,可以向某个进程发送指定的信号。

      ●远程ssh终端情况下,如果你在服务器上执行了一个阻塞的脚本,正在阻塞过程中你关闭了终端,可能就会产生SIGHUP信号。

      ●硬件也会产生信号,比如OOM了或者遇到除0这种情况,硬件也会向进程发送特定信号。

      而进程在收到信号后,可以有如下三种响应:

      ●直接忽略,不做任何反映。就是俗称的完全不鸟。但是有两种信号,永远不会被忽略,一个是SIGSTOP,另一个是SIGKILL,因为这两个进程提供了向内核最后的可靠的结束进程的办法。

      ●捕捉信号并作出相应的一些反应,具体响应什么可以由用户自己通过程序自定义。

      ●系统默认响应。大多数进程在遇到信号后,如果用户也没有自定义响应,那么就会采取系统默认响应,大多数的系统默认响应就是终止进程。

      PHP信号处理案例

      我们在FPM模式下写代码,不会遇到信号处理相关的问题,但是CLI模式下一些常驻内存的脚本,如何能够自由的重启、关闭、退出前做一些清理工作(断开链接,删除临时文件等)?

      配图2 PHP如何优雅的处理信号.jpg

      pcntl_signal是PHP的信号处理注册方法,这个是pcntl初始化的时候,将pcntl_signal_dispatch注册为tick的处理函数。

      配图3 PHP如何优雅的处理信号.jpg

      pcntl_signal会将处理函数放到信号集合中(PHP的hash table),而php_signale4最终会调用sigaction进行底层的信号管理。

      配图4 PHP如何优雅的处理信号.jpg

      这里我省略了大量代码,将关键的点标记了出来,其实PHP维护一个自己的信号集合,每当调用 pcntl_signal_dispatch时就会查询是否有信号,上面的SIG_BLOCK会将信号阻塞,这样只有我们把关键的代码执行完毕之后,再去触发信号处理函数以保证数据和程序逻辑的完整性。

      PHP如何优雅的处理信号

      经常见到身边的程序员们,每当需要重启PHP-FPM进程的时候,使用的招数是kill掉所有PHP进程,然后新启动。一般情况没啥问题,但有些时候可能某个进程的任务还没执行完,直接把人家中断了略显粗暴。

      其实只要你给PHP的Master进程发送一条USR2信号,它便会再处理完所有任务后,重启子进程,这才是所谓的优雅。

      配图5 PHP如何优雅的处理信号.jpg

      以上图为例,如果我们想让进程优雅退出的时候,只需要发送SIGTERM信号即可。需要注意的是SIGKILL和SIGSTOP信号会略过信号阻塞会将进程直接停止,还有就是信号会中断睡眠(SLEEP),sleep如果没执行完会返回剩下的秒数。

      信号相关的知识点其实有很多,还需要大家在平时的使用中继续深入研究。以上就是这篇文章的全部内容,希望能对大家有所帮助。