Zend Signal in PHP 5.4
2011-10-19 00:00
1531 查看
在PHP5.4中, 根据由Rasmus提交的RFC, 引入了一套新的信号处理机制, 目的是为了使得信号屏蔽机制可以应用到任何SAPI中, 并且提高在这个过程中的PHP性能.
新的机制, 叫做zend signal, 它的理念, 来自Yahoo的”延迟信号处理”(Yahoo signal deferring mechanism), 而后, facebook把这套理念加入了PHP中, 为了提升PHP+Apache 1.X下PHP调用ap_block/ap_unblock的性能.
在详细介绍之前, 我想还是先介绍下引入这个新机制的背景:
之前我写过俩篇blog, 介绍过因为超时信号导致PHP crash的案例:深入理解PHP内存管理之一个低概率Core的分析和一个低概率的PHP Core dump , 在其中, 我说过, 其实PHP在关键操作的时候, 是预留了信号屏蔽机制的:HANDLE_BLOCK和UNBLOCK_INTERRUPTIONS. 但是, 这俩个宏只是Hook, 需要SAPI自己去实现, 目前来说, 也只有Apache 1.x的SAPI实现了这俩个宏, 也就是使用ap_block和ap_unblock.
而对于”一个低概率的PHP Core dump “中所描述的情况, 如果我们为了解决它, 而在每次有错误发生的时刻, 都引入一对屏蔽/取消屏蔽的系统调用, 那么这个性能损失将会很明显, 所以一直没有很好的解决这个问题.
那么zend signal的做法是:
1. 在zend engine启动时刻, 会为下面的信号注册信号处理函数: SIGALRM, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2, SIGPROF(*nix下), 如果这些信号已经有了处理函数, 那么会把旧的处理函数保存下来.
2. 当有信号发生时候, zend_signal_handler_defer会首先判断, 当前是否处于block区域, 如果不是, 则信号对应的旧的处理函数将会被调用. 如果是, 那么信号处理函数不会被立即调用, 而是一直等到HANDLE_UNBLOCK_INTERRUPTIONS以后, 退出block区域, 才调用信号处理函数. 如果有多个信号发生, 则信号将会排队等候.
3. zend signal使用zend_signal_globals_t.depth计数, 来判断是否处于block区域, HANDLE_BLOCK递增, HANDLE_UNBLOCK_INTERRUPTIONS递减.当 zend_signal_globals_t.depth大于0, 则表示在block中, 否则就表示不在. 这样就保证了性能(避免以前调用sigaction来屏蔽信号).
另外, zend signal为PHP提供了新的信号处理注册接口: zend_signal.
更加详细的信息, 可以参看[RFC]Zend Singal
在zend signal引入的大背景下, 我终于解决了文章开头所说的超时信号可能导致crash的问题:#60038. (only in 5.4)
不过, 还是要提醒下: PHP 5.4还处于开发阶段, 在最终release之前, 任何新特性都可能被调整或者更改. 如果大家有任何建议, 也欢迎反馈, 帮助我们使得PHP变得更好.
谢谢
新的机制, 叫做zend signal, 它的理念, 来自Yahoo的”延迟信号处理”(Yahoo signal deferring mechanism), 而后, facebook把这套理念加入了PHP中, 为了提升PHP+Apache 1.X下PHP调用ap_block/ap_unblock的性能.
在详细介绍之前, 我想还是先介绍下引入这个新机制的背景:
之前我写过俩篇blog, 介绍过因为超时信号导致PHP crash的案例:深入理解PHP内存管理之一个低概率Core的分析和一个低概率的PHP Core dump , 在其中, 我说过, 其实PHP在关键操作的时候, 是预留了信号屏蔽机制的:HANDLE_BLOCK和UNBLOCK_INTERRUPTIONS. 但是, 这俩个宏只是Hook, 需要SAPI自己去实现, 目前来说, 也只有Apache 1.x的SAPI实现了这俩个宏, 也就是使用ap_block和ap_unblock.
而对于”一个低概率的PHP Core dump “中所描述的情况, 如果我们为了解决它, 而在每次有错误发生的时刻, 都引入一对屏蔽/取消屏蔽的系统调用, 那么这个性能损失将会很明显, 所以一直没有很好的解决这个问题.
那么zend signal的做法是:
1. 在zend engine启动时刻, 会为下面的信号注册信号处理函数: SIGALRM, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2, SIGPROF(*nix下), 如果这些信号已经有了处理函数, 那么会把旧的处理函数保存下来.
2. 当有信号发生时候, zend_signal_handler_defer会首先判断, 当前是否处于block区域, 如果不是, 则信号对应的旧的处理函数将会被调用. 如果是, 那么信号处理函数不会被立即调用, 而是一直等到HANDLE_UNBLOCK_INTERRUPTIONS以后, 退出block区域, 才调用信号处理函数. 如果有多个信号发生, 则信号将会排队等候.
3. zend signal使用zend_signal_globals_t.depth计数, 来判断是否处于block区域, HANDLE_BLOCK递增, HANDLE_UNBLOCK_INTERRUPTIONS递减.当 zend_signal_globals_t.depth大于0, 则表示在block中, 否则就表示不在. 这样就保证了性能(避免以前调用sigaction来屏蔽信号).
另外, zend signal为PHP提供了新的信号处理注册接口: zend_signal.
更加详细的信息, 可以参看[RFC]Zend Singal
在zend signal引入的大背景下, 我终于解决了文章开头所说的超时信号可能导致crash的问题:#60038. (only in 5.4)
不过, 还是要提醒下: PHP 5.4还处于开发阶段, 在最终release之前, 任何新特性都可能被调整或者更改. 如果大家有任何建议, 也欢迎反馈, 帮助我们使得PHP变得更好.
谢谢
相关文章推荐
- PHP5.4的变化关注---What has changed in PHP 5.4.x
- 编译php5.4的时候出现错误----configure: error: in `/usr/local/src/php540/php-5.4.0':
- Array of country list in PHP with Zend Framework
- PHP5.4的变化关注---What has changed in PHP 5.4.x
- PHP5.4上传进度支持(Upload progress in sessions)
- PHP Warning: Xdebug MUST be loaded as a Zend extension in Unknown on line 0 解决办法
- PHP5.4的变化关注---What has changed in PHP 5.4.x(转)
- PHPRPC模式在 php 5.4 版本下的错误Cannot redeclare gzdecode() in compat.php on line 182
- Array of country list in PHP with Zend Framework
- linux下php5.4安装Zend Guard Loader扩展
- linux下php5.4安装Zend Guard Loader扩展
- RedHat5.4上架设Apache+Mysql+Php+GD+ZendOptimizer+Phpmyadmin笔记
- 解决Zend加密的PHP页面出现Fatal error: Incompatible file format: The encoded file has format major ID 1, whereas the Loader expects 4 in
- ZendDebugger For PHP5.3 & PHP5.4
- Zend Guard6.0正式破解版 支持php5.3/5.4脚本加密
- Big Performance Increased for Drupal in PHP 5.4
- php5.4配置Zend Guard Loader v3.3
- 解决linux 下php中xdebug的报错 :Xdebug MUST be loaded as a Zend extension in Unknown on line 0
- 关于PHP文件加密--ZendGuard-6_0_0以及ZendGuardLoader-70429-PHP-5.4-Windows-x86