在使用PHP的PCNTL拓展时,发如今信号捕捉的例程中出现了declare(ticks=1)这条php语句,因而对其进行研究。php
一. 语句在php中的意义
php中,declare(ticks=n)和register_tick_function(‘handel_function’)通常是配合使用的,其做用是在zend解释器每执行 N 条可计时的低级语句就会发生的事件,该事件发生后就能够处理已经注册的函数’handel_function’;linux
二. 在使用捕捉信号时使用该语句的思考
1.linux下应用编程中的signal机制(linux-signal机制资料来源博客《Linux 信号signal处理机制》)编程
每一个进程都会采用一个进程控制块对其进行描述,进程控制块中设计了一个signal的位图信息,其中的每位与具体的signal相对应,这与中断机制是保持一致的。当系统中一个进程A经过signal系统调用向进程B发送signal时,设置进程B的对应signal位图,相似于触发了signal对应中断。发送signal只是“中断”触发的一个过程,具体执行会在两个阶段发生:api
(1)、 system call返回。进程B因为调用了system call后,从内核返回用户态时须要检查他拥有的signal位图信息表,此时是一个执行点。安全
(2)、 中断返回。进程被系统中断打断以后,系统将CPU交给进程时,须要检查即将执行进程所拥有的signal位图信息表,此时也是一个执行点。函数
综上所述,signal的执行点能够理解成从内核态返回用户态时,在返回时,若是发现待执行进程存在被触发的signal,那么在离开内核态以后(也就是将CPU切换到用户模式),执行用户进程为该signal绑定的signal处理函数,从这一点上看,signal处理函数是在用户进程上下文中执行的。当执行完signal处理函数以后,再返回到用户进程被中断或者system call(软中断或者指令陷阱)打断的地方。.net
2.php使用singal为何须要使用declare(ticks=n)语句
既然系统内核都提供了完整的signal的机制,第一想到的是,pcntl拓展要实现php的signal-api, 其直接将php方法与底层的singnal函数绑定就能实现了,不是吗?设计
(如下对于该问题的答案纯属我的思考)
答案是否认的,从上面linux中的signal机制可知道,其机制是针对c语言等强语言的,其对代码的中断形成对变量的影响是可控的。code
可是对于PHP这样的脚本语言,一个语句底下多是n句C语言执行,或者n+m句机器指令,若是在一条语句的执行过程当中运行php的signal函数,那么极可能引发php的奔溃;进程
那么pcntl拓展怎么解决这个问题了,天然就会想到,若是信号来了先作标记,再等一句完整的php语句执行完了,而后再调用使用pcntl_signal注册的php回调函数,这样就保证了php环境的安全性。
而php中declare(ticks=n)和register_tick_function(‘handel_function’)就提供了这样的功能;
结论很清楚了,为了保证php环境的安全性和稳定性,pcntl拓展在实现signal上使用了“延后执行”的机制;所以使用该功能时,必须先使用语句declare(ticks=1),不然注册的singal-handel就不会执行了
declare 结构用来设定一段代码的执行指令。declare 的语法和其它流程控制结构类似:
declare (directive) statement
directive 部分容许设定 declare 代码段的行为。目前只有两个指令:ticks(更多信息见下面 ticks 指令)以及 encoding(更多信息见下面 encoding 指令)。
declare 代码段中的 statement 部分将被执行——怎样执行以及执行中有什么反作用出现取决于 directive 中设定的指令。
declare 结构也可用于全局范围,影响到其后的全部代码(但若是有 declare 结构的文件被其它文件包含,则对包含它的父文件不起做用)。
Tick(时钟周期)是一个在 declare 代码段中解释器每执行 N 条可计时的低级语句就会发生的事件。N 的值是在 declare 中的 directive 部分用 ticks=N
来指定的。
不是全部语句均可计时。一般条件表达式和参数表达式都不可计时。
在每一个 tick 中出现的事件是由 register_tick_function() 来指定的。