【1、信号】
对于Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。
1、信号的种类
这里列举1-31号信号。剩余的信号请查看kill -l
编号 | 信号名称 | 默认动作 | 说明 |
---|---|---|---|
1 | SIGHUP | 进程终止 | 终止控制终端或进程 |
2 | SIGINT | 进程终止 | 键盘产生的中断(Ctrl+C) |
3 | SIGQUIT | 进程终止 | 键盘产生的退出 |
4 | SIGILL | 进程终止 | 非法指令 |
5 | SIGTRAP | 进程终止 | debug中断 |
6 | SIGABRT/SIGIOT | 进程终止 | 发生异常终止 |
7 | SIGBUS/SIGEMT | 进程终止 | 总线异常/EMT指令 |
8 | SIGFPE | 进程终止 | 浮点运算溢出 |
9 | SIGKILL | 进程终止 | 强制进程终止 |
10 | SIGUSR1 | 进程终止 | 用户信号,进程可自定义用途 |
11 | SIGSEGV | 进程终止 | 非法内存地址引用 |
12 | SIGUSR2 | 进程终止 | 用户信号,进程可自定义用途 |
13 | SIGPIPE | 进程终止 | 向某个没有读取的管道中写入数据 |
14 | SIGALRM | 进程终止 | 时钟中断(闹钟) |
15 | SIGTERM | 进程终止 | 进程终止 |
16 | SIGSTKFLT | 进程终止 | 协处理器栈错误 |
17 | SIGCHLD | 忽略 | 子进程退出或中断 |
18 | SIGCONT | 继续运行 | 如进程停止状态则开始运行 |
19 | SIGSTOP | 进程暂停 | 停止进程运行 |
20 | SIGSTP | 进程暂停 | 键盘产生的停止 |
21 | SIGTTIN | 进程暂停 | 后台进程请求输入 |
22 | SIGTTOU | 进程暂停 | 后台进程请求输出 |
23 | SIGURG | 忽略 | socket发生紧急情况 |
24 | SIGXCPU | 进程终止 | CPU时间限制被打破 |
25 | SIGXFSZ | 进程终止 | 文件大小限制被打破 |
26 | SIGVTALRM | 进程终止 | 虚拟定时时钟 |
27 | SIGPROF | 进程终止 | profile timer clock |
28 | SIGWINCH | 忽略 | 窗口尺寸调整 |
29 | SIGIO/SIGPOLL | 进程终止 | I/O可用 |
30 | SIGPWR | 进程终止 | 电源异常 |
31 | SIGSYS/SYSUNUSED | 进程终止 | 系统调用异常 |
* 注:Linux操作系统定义的62
个信号,每个信号都有对应的一个编号和宏定义名称,这些宏定义可以在 kill - l 中找到。其中1-31
号信号为普通信号
,34-64
号信号为实时信号
,一旦发出信号则立即去处理。
【2、 PHP如何给进程安装信号处理】
php版本低于5.3时的策略思路:每次执行一条语句检测是否有信号发送给程序;由于不知道什么时候会有信号过来,所以需要逐步检查,导致效率很低
<?php
//设置每次执行一条语句检测是否有信号
declare(ticks=1);
//注册信号处理函数
register_tick_function('sigal');
//根据信号处理逻辑
function sigal($sigal)
{
echo $sigal;
}
while(1)
{
sleep(1);
}
php版本在5.3以后 7以下的时候采取的是 pcntl_signal_dispatch
<?php
//注册当前进程的信号处理
pcntl_signal_dispatch();
//注册 发生SIGINT 对应的处理逻辑
pcntl_signal(SIGINT,function(){
//to do...
});
while(true)
{
sleep(1);
}
php版本在7以后 采取的是异步处理 (效率最高)
<?php
//设置当前进程信号异步处理
pcntl_async_signals(true);
pcntl_signal(SIGINT,function(){
//to do ...
});
while(true)
{
sleep(1);
}
【3、简单举例】
需求:程序在30秒后自动退出(php7版本);
<?php
//注册当前异步处理信号模块
pcntl_async_signals(true);
//注册自定义信号
pcntl_signal(SIGUSR1,function(){
echo '出发了自定义信号,进程执行退出'.PHP_EOL;
posix_kill(getmypid(),SIGQUIT);
});
//设定初始时间
$time=0;
while(true)
{
//如果大于30秒就触发自定义信号
if($time>30) posix_kill(getmypid(),SIGUSR1);
sleep(1);
$time++;
}
过了30秒后,进程执行退出。
【4、注意事项】
注意: 9号信号 不可被捕捉。 系统保留用于强制退出进程;