快一个月没发博文了,之前都在深入研究php多进程tcp服务器,结果到现在也没搞出一个完美的解决方案,所以还是先发下这个月学到的东西吧
注意:本文所有内容均在linux环境下
在php进程信号常量中,有定义以下常量(该表格参考网上的,不完整)
<!--br {mso-data-placement:same-cell; }td {color:#303030; font-size:12.0pt; font-family:宋体; font-weight:400; font-style:normal; text-decoration:none; text-align:general; vertical-align:middle; mso-number-format:General; mso-protection:locked visible; }.et2 {color:#303030; font-size:12.0pt; font-family:宋体; font-weight:400; font-style:normal; text-decoration:none; text-align:general; vertical-align:middle; mso-number-format:General; mso-protection:locked visible; }-->
信号名 | 信号值 | 信号类型 | 信号说明 |
---|---|---|---|
SIGHUP | 1 | 终止进程(终端线路挂断) | 本信号在用户终端连接(正常或非正常、结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联. |
SIGINT | 2 | 终止进程(中断进程) | 程序终止(interrupt、信号, 在用户键入INTR字符(通常是Ctrl-C、时发出 |
SIGQUIT | 3 | 建立CORE文件终止进程,并且生成CORE文件 | SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-、来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信 号. |
SIGILL | 4 | 建立CORE文件(非法指令) | SIGILL 执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号. |
SIGTRAP | 5 | 建立CORE文件(跟踪自陷) | SIGTRAP 由断点指令或其它trap指令产生. 由debugger使用. |
SIGABRT | 6 | SIGABRT 程序自己发现错误并调用abort时产生. | |
SIGIOT | 6 | 建立CORE文件(执行I/O自陷) | SIGIOT 在PDP-11上由iot指令产生, 在其它机器上和SIGABRT一样. |
SIGBUS | 7 | 建立CORE文件(总线错误) | SIGBUS 非法地址, 包括内存地址对齐(alignment、出错. eg: 访问一个四个字长的整数, 但其地址不是4的倍数. |
SIGFPE | 8 | 建立CORE文件(浮点异常) | SIGFPE 在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢 出及除数为0等其它所有的算术的错误. |
SIGKILL | 9 | 终止进程(杀死进程) | SIGKILL 用来立即结束程序的运行. 本信号不能被阻塞, 处理和忽略. |
SIGUSR1 | 10 | 终止进程(用户自定义信号1) | SIGUSR1 留给用户使用 |
SIGSEGV | 11 | SIGSEGV 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据. | |
SIGUSR2 | 12 | 终止进程(用户自定义信号2) | SIGUSR2 留给用户使用 |
SIGPIPE | 13 | 终止进程(向一个没有读进程的管道写数据) | Broken pipe |
SIGALRM | 14 | 终止进程(计时器到时) | SIGALRM 时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该信号. |
SIGTERM | 15 | 终止进程(软件终止信号) | SIGTERM 程序结束(terminate、信号, 与SIGKILL不同的是该信号可以被阻塞和处理. 通常用来要求程序自己正常退出. shell命令kill缺省产生这个信号. |
SIGCHLD | 17 | 忽略信号(当子进程停止或退出时通知父进程) | SIGCHLD 子进程结束时, 父进程会收到这个信号. |
SIGCONT | 18 | 忽略信号(继续执行一个停止的进程) | SIGCONT 让一个停止(stopped、的进程继续执行. 本信号不能被阻塞. 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定的工作. 例如, 重新显示提示符 |
SIGSTOP | 19 | 停止进程(非终端信号) | SIGSTOP 停止(stopped、进程的执行. 注意它和terminate以及interrupt的区别: 该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略. |
SIGTSTP | 20 | 停止进程(终端信号) | SIGTSTP 停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时 (通常是Ctrl-Z、发出这个信号 |
SIGTTIN | 21 | 停止进程(后端进程读终端) | SIGTTIN 当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN 信号. 缺省时这些进程会停止执行. |
SIGTTOU | 22 | 停止进程(后端进程写终端) | SIGTTOU 类似于SIGTTIN, 但在写终端(或修改终端模式、时收到. |
SIGURG | 23 | 忽略信号(I/O紧急信号) | SIGURG 有”紧急”数据或out-of-band数据到达socket时产生. |
SIGXCPU | 24 | 终止进程(CPU实现超时) | SIGXCPU 超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/ 改变 |
SIGXFSZ | 25 | 终止进程(文件长度过长) | SIGXFSZ 超过文件大小资源限制. |
SIGVTALRM | 26 | 终止进程(虚拟计时器到时) | SIGVTALRM 虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间. |
SIGPROF | 27 | 终止进程(统计分布图用计时器到时) | SIGPROF 类似于SIGALRM/SIGVTALRM, 但包括该进程用的CPU时间以及系统调用的 时间. |
SIGWINCH | 28 | 忽略信号(窗口大小发生变化) | SIGWINCH 窗口大小改变时发出. |
SIGIO | 29 | 忽略信号(描述符上可以进行I/O) | SIGIO 文件描述符准备就绪, 可以开始进行输入/输出操作. |
SIGPWR | 30 | SIGPWR Power failure |
注意:(需要pcntl扩展支持)
具体相关函数可查看php手册:http://php.net/manual/zh/book.pcntl.php
<?php
declare(ticks=1);//每执行一条时,触发register_tick_function()注册的函数
$a=1;//再注册之前,不记录
$a=1;//再注册之前,不记录
function test(){//定义一个函数
echo "执行\n";
}
register_tick_function('test');//该条注册函数会被当成低级语句被执行
for($i=0;$i<=3;$i++){//for算一条低级语句
$i=$i;//赋值算一条
}
在php7.2中,运行结果如下:
declare(ticks = 1);
pcntl_signal(SIGINT,function(){
echo "触发信号Ctrl+c";
});
while(1){
sleep(1);//死循环运行低级语句
}
当执行该脚本,再ctrl+c的时候,将会捕捉到该信号,并输出,如图:
为什么会拿这2个一起说呢?因为posix_kill函数如果需要发送信号,是需要进程id的,而getmypid(),则是获取当前进程id的函数,
以下是将上面的函数组合使用的例子:
<?php
//文件一
declare(ticks = 1);
echo getmypid();//获取当前进程id
pcntl_signal(SIGUSR1,function(){
echo "触发信号用户自定义信号1";
});
while(1){
sleep(1);//死循环运行低级语句
}
<?php
//文件二
posix_kill(文件一进程, SIGUSR1);
运行文件1结果:
运行文件2之后文件1结果:
pcntl_signal_dispatch: 调用等待信号的处理器,有了它,将不在需要declare,只需要在循环中增加该函数,就可以调用信号通过了:
<?php
echo getmypid();//获取当前进程id
pcntl_signal(SIGUSR1,function(){
echo "触发信号用户自定义信号1";
});
while(1){
pcntl_signal_dispatch();
sleep(1);//死循环运行低级语句
}
结果和3同样
<?php
//文件一
echo getmypid();
pcntl_async_signals(true);//设置异步信号
pcntl_signal(SIGUSR1,function(){//安装个user1信号处理函数
echo "触发信号";
posix_kill(getmypid(),SIGSTOP);
});
posix_kill(getmypid(),SIGSTOP);//给进程发送暂停信号
<?php
//文件2
posix_kill(文件1进程, SIGCONT);//给进程发送继续信号
posix_kill(文件1进程, SIGUSR1);//给进程发送user1信号
首先文件1运行,再给文件2运行之后,文件1的结果图:
文件1进程strace 命令截图:
可看到,进程休眠之后,被9271进程(文件2)唤醒之后并发送了siguse1信号,再然后输出了一段文字,再然后自己给自己发送了进程休眠信号,继续休眠
linux 查看进程命令.可看:
https://blog.csdn.net/liangzhao_jay/article/details/50457197
<?php
pcntl_signal(SIGALRM, function () {
echo '定时到时' . PHP_EOL;
});
pcntl_alarm(5);
$i=0;
while(1){
echo $i.PHP_EOL;$i++;
pcntl_signal_dispatch();
sleep(1);
}
该函数使用场景之一:php熔断
<?php
pcntl_async_signals(true);
pcntl_signal(SIGALRM, function () {
echo 'php处理超时' . PHP_EOL;
});
pcntl_alarm(30);
/*
* 这里是一大段php处理函数
* */
pcntl_alarm(-1);
先进行30秒的定时,当处理函数超过30秒时,将触发php处理超时函数,从而进行超时逻辑,当在30秒处理完毕时,php将关闭改定时信号,正常往下执行
1:php进程信号中,无法捕获SIGKILL信号,该信号将会强制关闭进程