写给PHP程序员的信号处理教程

今天晚上吃卤煮,领桌的妹子问我,这玩意儿能吃么?我:你以为能吃就能吃。。。和内容无关的主题

什么是信号

信号就是事件发生时,对进程的一种通知机制(也叫软件中断)。当一个进程收到信号后,内核会暂停该进程正在执行的代码,并跳转到对应的信号处理函数中,若是处理函数不中断,执行完处理函数后,会继续执行以前中断的地方往下执行。php

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

C的信号处理举例

C的信号处理举例

上图中,我为信号SIGINT注册了处理函数sigint_handle,捕获到信号后,输出内容后退出,简单易懂吧。执行 gcc -o run run.c && ./run ,而后CTRL+C(会触发SIGINT信号),成功输出:成功捕获到信号2!,程序直接结束运行。小程序

PHP的信号处理举例

PHP的信号处理举例

pcntl_signal是PHP的信号处理注册方法,上面实现的功能和C实现的基本一致,不一样的是,当前进程不会退出,而且多输出了一个signinfo(PHP是C写的,为啥刚刚C语言的没有信号相关的信息呢?由于PHP使用的是另外一个信号函数sigaction,有兴趣的能够了解一下)函数

PHP的信号处理并非直接调用C

tick

这个是pcntl初始化的时候,将pcntl_signal_dispatch注册为tick的处理函数spa

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

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

PHP如何优雅的处理信号

常常见到身边的程序员们,每当须要重启PHP-FPM进程的时候,使用的招数是kill掉全部PHP进程,而后新启动。通常状况没啥问题,但有些时候可能某个进程的任务还没执行完,直接把人家中断了略显粗暴。其实只要你给PHP的Master进程发送一条USR2信号,它便会再处理完全部任务后,重启子进程,这才是所谓的优雅~进程

sigterm

上图是我简单写的一个例子,若是咱们想让进程优雅退出的时候,只须要发送SIGTERM信号便可。须要注意的是SIGKILLSIGSTOP信号会略过信号阻塞会将进程直接中止,还有就是信号会中断睡眠(SLEEP),sleep若是没执行完会返回剩下的秒数,有兴趣能够试试。事件

信号相关的知识点其实有不少,还须要继续深刻研究~上文中的PHP源码为7.1.25版本,各个版本可能不太同样。图片

开发了一个数独小程序「惟一数独」,欢迎扫描玩起来~

图片描述

相关文章
相关标签/搜索