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

php进程间通信的另外一个手段就是通过信号来在进程间传递信息 。信号是一种系统调用 , 通常我们用的kill命令就是发送某个信号给某个进程的 。
在开发服务器端守护进程方面 , 信号处理至关重要 。PHP的pcntl扩展提供了信号处理的功能 , 利用它可以让PHP来接管信号的处理 。

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

文章插图
 
今天 , 我们就来给大家讲一讲PHP中的信号处理 。
什么是信号?信号是事件发生时对进程的通知机制 , 有时又称为软件中断 。一个进程可以向另一个进程发送信号 , 比如子进程结束时都会向父进程发送一个SIGCHLD(17号信号)来通知父进程 , 所以有时信号也被当作一种进程间通信的机制 。
信号的产生是有多种方式的 , 下面是常见的几种:
●键盘上按某些组合键 , 比如Ctrl+C或者Ctrl+D等 , 会产生SIGINT信号 。
●使用posix kill调用 , 可以向某个进程发送指定的信号 。
●远程ssh终端情况下 , 如果你在服务器上执行了一个阻塞的脚本 , 正在阻塞过程中你关闭了终端 , 可能就会产生SIGHUP信号 。
●硬件也会产生信号 , 比如OOM了或者遇到除0这种情况 , 硬件也会向进程发送特定信号 。
而进程在收到信号后 , 可以有如下三种响应:
●直接忽略 , 不做任何反映 。就是俗称的完全不鸟 。但是有两种信号 , 永远不会被忽略 , 一个是SIGSTOP , 另一个是SIGKILL , 因为这两个进程提供了向内核最后的可靠的结束进程的办法 。
●捕捉信号并作出相应的一些反应 , 具体响应什么可以由用户自己通过程序自定义 。
●系统默认响应 。大多数进程在遇到信号后 , 如果用户也没有自定义响应 , 那么就会采取系统默认响应 , 大多数的系统默认响应就是终止进程 。
PHP信号处理案例我们在FPM模式下写代码 , 不会遇到信号处理相关的问题 , 但是CLI模式下一些常驻内存的脚本 , 如何能够自由的重启、关闭、退出前做一些清理工作(断开链接 , 删除临时文件等)?
PHP如何优雅的处理信号?看完这篇文章你就知道了

文章插图
 
pcntl_signal是PHP的信号处理注册方法 , 这个是pcntl初始化的时候 , 将pcntl_signal_dispatch注册为tick的处理函数 。
PHP如何优雅的处理信号?看完这篇文章你就知道了

文章插图
 
pcntl_signal会将处理函数放到信号集合中(PHP的hash table) , 而php_signale4最终会调用sigaction进行底层的信号管理 。
PHP如何优雅的处理信号?看完这篇文章你就知道了

文章插图
 
这里我省略了大量代码 , 将关键的点标记了出来 , 其实PHP维护一个自己的信号集合 , 每当调用 pcntl_signal_dispatch时就会查询是否有信号 , 上面的SIG_BLOCK会将信号阻塞 , 这样只有我们把关键的代码执行完毕之后 , 再去触发信号处理函数以保证数据和程序逻辑的完整性 。
PHP如何优雅的处理信号经常见到身边的程序员们 , 每当需要重启PHP-FPM进程的时候 , 使用的招数是kill掉所有PHP进程 , 然后新启动 。一般情况没啥问题 , 但有些时候可能某个进程的任务还没执行完 , 直接把人家中断了略显粗暴 。
其实只要你给PHP的Master进程发送一条USR2信号 , 它便会再处理完所有任务后 , 重启子进程 , 这才是所谓的优雅~
PHP如何优雅的处理信号?看完这篇文章你就知道了

文章插图
 
以上图为例 , 如果我们想让进程优雅退出的时候 , 只需要发送SIGTERM信号即可 。需要注意的是SIGKILL和SIGSTOP信号会略过信号阻塞会将进程直接停止 , 还有就是信号会中断睡眠(SLEEP),sleep如果没执行完会返回剩下的秒数 。
信号相关的知识点其实有很多 , 还需要大家在平时的使用中继续深入研究 。以上就是这篇文章的全部内容 , 希望能对大家有所帮助 。

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


    推荐阅读