信号是一种软中断,ipc通信中的一种,也是唯一的异步通信方式。在linux下,我们可以使用 kill -l 查看系统里面支持的所有信号,发送信号给某个进程可以使用 kill -信号类型 pid 给指定的pid。在php中,我们使用 posxi_kill 来实现信号的发送。
posix_kill向进程发送信号的几种作用:
1、发送信号给指定的进程
posix_kill("进程号",9);
2、检测进程是否存活,返回true表示进程存在,反之返回false
$res=posix_kill("进程号",0);
3、向当前进程组发送信号,9强制退出,当然也可以使用常量 SIGKILL, 0是特殊的进程,表示进程组里面所有的进程。
posix_kill(0,9);
在php中使用信号处理,在php5.3以前,使用declare语句来检测信号,我们来看demo1:
vim demo1
#!/usr/local/php/bin/php
<?php
declare(ticks = 1);
pcntl_signal(SIGINT, function(){
echo "信号触发\n";
});
$i=1;
while(true){
$i++;
echo $i,"\n";
sleep(1);
}
保存退出,设置脚本可执行并执行之
chmod +x demo1 && ./demo1
这时程序就会不断输出$i的值,我们使用 ctrl+c ,就会向当前进程发送信号,输出信号触发了,因为接管了信号,所以就没有退出。使用ctrl+\ 强制退出。
下面我们来看第二种方式demo2,使用pcntl_signal_dispatch 函数来实现,
#!/usr/local/php/bin/php
<?php
pcntl_signal(SIGINT, function(){
echo "信号触发\n";
});
$i=0;
while(true){
pcntl_signal_dispatch();
$i++;
echo $i,"\n";
sleep(1);
}
测试方式一样, 也是 ctrl+c ,ctrl+\ , 使用pcntl_signal_dispatch 会比 tick消耗更少的cpu。
第三种方式,在php7.1.0之后,新增了函数 pcntl_async_signals 来实现信号的处理,demo3
#!/usr/local/php/bin/php
<?php
pcntl_async_signals(true);
pcntl_signal(SIGINT, function(){
echo "信号触发\n";
});
$i=0;
while(true){
$i++;
echo $i,"\n";
sleep(1);
}
测试方式一样, 也是 ctrl+c ,ctrl+\ , 采用异步信号的方式实现。由于php7.1.0还比较新,为了做兼容,我们可以这么写demo4:
#!/usr/local/php/bin/php
<?php
if(version_compare(PHP_VERSION, '7.1.0')>=0){
pcntl_async_signals(true);
}
pcntl_signal(SIGINT, function(){
echo "信号触发\n";
});
$i=0;
while(true){
if(version_compare(PHP_VERSION, '7.1.0')<0){
pcntl_signal_dispatch();
}
$i++;
echo $i,"\n";
sleep(1);
}
注册多个信号的例子1:
#!/usr/local/php/bin/php
<?php
class Test
{
public function handler($sig)
{
echo "信号值:" . $sig . "信号触发\n";
}
public function run()
{
pcntl_async_signals(true);
pcntl_signal(SIGINT, [ & $this, "handler"]);
pcntl_signal(SIGUSR1, [ & $this, "handler"]);
pcntl_signal(SIGUSR2, [ & $this, "handler"]);
}
}
$p1 = new Test();
$p1->run();
$i = 0;
while (true) {
$i++;
echo $i, "\n";
sleep(1);
}
当然也可以是静态类:
#!/usr/local/php/bin/php
<?php
class Test
{
public static function handler($sig)
{
echo "信号值:" . $sig . "信号触发\n";
}
public static function run()
{
pcntl_async_signals(true);
pcntl_signal(SIGINT, ['Test', "handler"]);
pcntl_signal(SIGUSR1, ['Test', "handler"]);
pcntl_signal(SIGUSR2, ['Test', "handler"]);
}
}
Test::run();
$i = 0;
while (true) {
$i++;
echo $i, "\n";
sleep(1);
}