Linux操作系统中有哪些标志? PHP 中信号处理相关的函数和方法
1. Linux 操作系统中存在哪些信号
1. 信号简介
信号是“事情发生时的过程的一种通知方法,有时也称为” 软件停止。一个进程可以向其他进程发送信号。例如,当子进程终止时,它会向父进程发送SIGCHLD(信号号17)来通知父进程,所以有时该信号也被用作诸如进程间通信系统。
在Linux系统中,我们通常使用kill -9 XXPID来终止进程。实际上,该命令的本质是向进程发送SIGKILL(9号信号)。对于前端步骤,我们通常使用Ctrl+c键。要结束操作,快捷键的依据是向当前进程发送SIGINT(2号信号),进程收到这个信号时的正常行为是结束操作
2。常用令牌
对于以下令牌,可以使用kill -l 命令查看 这里有比较重要和常用的令牌:
令牌名称 | 令牌值 ” 信号说明 | ||
---|---|---|---|
SIGHUP | 1 | 停止进程(终端原因) | 当终端通信终止(正常或异常)时输出此信号,通常是在监听终端的进程之后,通知同一个会话中的各个任务,此时什么也没有与监控终端相关 |
SIGQUIT | 2 | 终止进程(中断进程) | 程序停止(中断,信号,当用户输入INTR字符时退出(通常是Ctrl-C, |
SIGQUIT | 3 | )创建CORE文件结束进程,并创建CORE文件 | 进程,并创建文件CORE SIGQUIT与SIGINT类似,但由QUIT属性控制(通常是Ctrl-)。进程因接收到SIGQUIT而退出时会生成一个core文件,类似于程序错误信号 |
SIGFPE | 8 | 创建CORE文件(非浮动) | SIGFPE发生致命错误时输出。发生。这不仅包括浮点运算错误,还包括溢出、除以 0 等所有其他错误。 算术错误 |
SIGKILL | 9 | 终止进程(杀死进程) | SIGKILL 用于立即结束进程。该程序。该信号无法被阻止、控制或忽略 |
SIGSEGV | 11 | SIGSEGV 尝试访问未分配的内存 分配自己的内存,或尝试将数据写入您没有写权限的内存地址 | |
SIGALRM | 14 | 步骤(超时) | SIGALRM 时钟信号,计算实际时间或时钟时间。 Alarm 该函数使用此信号 |
SIGTERM | 15 | 来终止进程(软件终止信号) | 程序结束 SIGTERM(结束,信号)。与 SIGKILL 不同,该信号可以被阻止和处理。常用于要求程序正常退出。 。 Kill shell 命令默认生成此信号 |
SIGCHLD | 17 | 忽略信号(当子进程停止或退出时通知父进程) | SIGCHLD 当子进程终止时,父进程会收到此信号母亲 |
SIGVTALRM | 26 | 终止进程(虚拟时间限制已过) | SIGVTALRM 虚拟时钟信号。与 SIGALRM 相同,但计算进程占用的 CPU 时间 |
SIGIO | 29 | 忘记信号(描述符上可能存在 I/O) | SIGIO 文件描述符准备就绪,可以开始输入操作/释放 |
2. PHP中与信号处理相关的函数
PHP的pcntl扩展和posix为我们提供了几种扩展方法。 (如果要使用这些功能,需要先安装这些扩展)
以下是我在这项工作中使用的几个方法:
declare
声明系统用于声明代码片段。执行声明指令的语法与其他控制系统类似。该指南的一部分允许您设置代码部分的行为。目前只知道两个命令:挤压和滚动。代码段中的语句部分会被执行——如何执行以及执行过程中会发生什么后果取决于指令中设置的指令
Ticks
Tick(时钟周期)是声明式中的解释器代码。每次执行由高级语句定义的N时将发生的N个事件的值由语句的指令部分中的ticks=N指定。并非所有报表都能按时提供。一般来说, 和这两个词都不能及时重复。每个tick发生的事件由register_tick_function()定义。请注意,每次点击可能会出现多个操作。更多信息参见官方文档:https://www.php.net/manual/zh/control-structs.declare.php pcntl_signal,设置信号处理器 函数pcntl_signal()为signo posix_kill指定的信号设置一个新的信号处理器,向进程 发送信号,第一个信号是进程ID,第二个是你要发送的信号。 pcntl_signal_dispatch,调用等待信号的处理器 函数 pcntl_signal_dispatch() 调用信号调度程序 pcntl als() 设置的等待 异步信号处理用于允许异步信号处理没有加密(这会带来很多额外的开销)。 (PHP>=7.1) 我们已经知道,我们可以通过语句(ticks=1)和pcntl_signal的组合来控制信号,即PHP最底层的语句会检查当前进程是否包含未处理的标识符。非常努力。 pcntl_signal的实现原理是初始化信号后插入序列中的第一个信号。然后继续检查 PHP 刻度回调函数中的标志。如果有信号,则执行PHP中指定的回调函数。如果没有,请跳过该工作。 PHP5.3之后有一个函数pcntl_signal_dispatch。此时,该声明已不再需要。只需要在循环中添加调用信号的函数,并通过: 大家都知道,PHP=1 的刻度意味着每有一行 PHP 代码就会调用这个函数。其实大部分时候是没有信号输出的,但是ticks的函数一直在执行。如果服务器程序在 1 秒内收到 1,000 个请求,则每个请求通常会执行 1,000 行 PHP。那么PHP的pcntl_signal又携带了1000 * 1000,也就是对空信号的100万次调用。这会消耗大量的CPU资源。更好的方法是解压并使用 pcntl_signal_dispatch 在代码循环中自行处理信号。 pcntl_signal_dispatch函数的实现: 但是上面的可恶之处在于它必须被置于无限循环中。 PHP7.1之后,发布了一个函数来完成异步信号接收和处理:pcntl_async_signals 有了pcntl_async_signals方法,就不需要再写死循环了。 指标包: 作者:Shulv<?php
declare(ticks=1);//每执行一条时,触发register_tick_function()注册的函数
$a=1;//在注册之前,不算
function test(){//定义一个函数
echo "执行\n";
}
register_tick_function('test');//该条注册函数会被当成低级语句被执行
for($i=0;$i<=2;$i++){//for算一条低级语句
$i=$i;//赋值算一条
}
输出:六个“执行”
复制代码
pcntl_signal
pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] ) : bool
复制代码
declare(ticks = 1);
pcntl_signal(SIGINT,function(){
echo "你按了Ctrl+C".PHP_EOL;
});
while(1){
sleep(1);//死循环运行低级语句
}
输出:当按Ctrl+C之后,会输出“你按了Ctrl+C”
复制代码
posix_kill
posix_kill ( int $pid , int $sig ) : bool
复制代码
a.php
<?php
declare(ticks = 1);
echo getmypid();//获取当前进程id
pcntl_signal(SIGINT,function(){
echo "你给我发了SIGINT信号";
});
while(1){
sleep(1);
}
b.php
<?php
posix_kill(执行1.php时输出的进程id, SIGINT);
复制代码
pcntl_signal_dispatch
pcntl_signal_dispatch ( void ) : bool
复制代码
<?php
pcntl_async_signals(true); // turn on async signals
pcntl_signal(SIGHUP, function($sig) {
echo "SIGHUP\n";
});
posix_kill(posix_getpid(), SIGHUP);
输出:
SIGHUP
复制代码
3。如何在PHP中处理信号量
PHP_MINIT_FUNCTION(pcntl)
{
php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
php_add_tick_function(pcntl_signal_dispatch TSRMLS_CC);
return SUCCESS;
}
复制代码
<?php
echo getmypid();//获取当前进程id
pcntl_signal(SIGUSR1,function(){
echo "触发信号用户自定义信号1";
});
while(1){
pcntl_signal_dispatch();
sleep(1);//死循环运行低级语句
}
复制代码
void pcntl_signal_dispatch()
{
//.... 这里略去一部分代码,queue即是信号队列
while (queue) {
if ((handle = zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo)) != NULL) {
ZVAL_NULL(&retval);
ZVAL_LONG(¶m, queue->signo);
/* Call php signal handler - Note that we do not report errors, and we ignore the return value */
/* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
call_user_function(EG(function_table), NULL, handle, &retval, 1, ¶m TSRMLS_CC);
zval_ptr_dtor(¶m);
zval_ptr_dtor(&retval);
}
next = queue->next;
queue->next = PCNTL_G(spares);
PCNTL_G(spares) = queue;
queue = next;
}
}
复制代码
<?php
//a.php
echo getmypid();
pcntl_async_signals(true);//开启异步监听信号
pcntl_signal(SIGUSR1,function(){
echo "触发信号";
posix_kill(getmypid(),SIGSTOP);
});
posix_kill(getmypid(),SIGSTOP);//给进程发送暂停信号
//b.php
posix_kill(文件1进程, SIGCONT);//给进程发送继续信号
posix_kill(文件1进程, SIGUSR1);//给进程发送user1信号
复制代码
https://github.com/Rain-Life/monitorSignal
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。