美文网首页
系统编程-信号

系统编程-信号

作者: aoshi | 来源:发表于2020-12-16 11:37 被阅读0次

    信号是事件发生时对进程的通知机制,有时又称为软件中断。一个进程可以向另一个进程发送信号,比如子进程结束时都会向父进程发送一个SIGCHLD(17号信号)来通知父进程,所以有时信号也被当作一种进程间通信的机制。

    在linux系统下,通常我们使用 kill -9 XXPID来结束一个进程,其实这个命令的实质就是向某进程发送 SIGKILL(9号信号),对于在前台运行的程序我们通常用 Ctrl + c 快捷键来结束运行,该快捷键的实质是向当前进程发送 SIGINT (2号信号),而进程收到该信号的默认行为是结束运行。我们可以用命令 kill -l 来查看系统的信号列表:

    image.png

    其中1 ~ 31 号信号为标准信号或者传统信号,而大于31号信号为实时信号,这里我们主要介绍 标准信号。进程收到一个信号时,视信号的不同,有以下几种不同的行为:
    1)忽略信号,进程就像没收到过信号一样,比如父进程收到子进程发送的 SIGCHLD 信号
    2)结束进程, 比如进程收到 SIGINT (Ctrl + c) 信号
    3)暂停运行
    4)从之前的暂停状态恢复运行

    PHP的pcntl扩展以及posix扩展为我们提供了若干操作信号的方法:

    pcntl_signal_dispatch — 调用等待信号的处理器
    pcntl_signal_get_handler — Get the current handler for specified signal
    pcntl_signal — 安装一个信号处理器
    pcntl_sigprocmask — 设置或检索阻塞信号
    pcntl_sigtimedwait — 带超时机制的信号等待
    pcntl_sigwaitinfo — 等待信号 
    posix_kill — 向一个进程发送信号
    
    pcntl_signal 方法可以让我们自定义进程对信号的处理动作,但是在linux系统中,SIGKILL(9号信号)和 SIGSTOP (19号信号)这两个信号是无法被我们自己捕获和处理的,SIGKILL总是会结束进程运行,SIGSTOP总是能暂停进程。
    bool pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] )
     
    signo
    信号编号
     
    handler
    信号处理器可以是用户创建的函数或方法的名字,也可以是系统常量 SIG_IGN(译注:忽略信号处理程序)或SIG_DFL(默认信号处理程序)
    

    在PHP中,有自己触发信号回调的机制

    PCNTL现在使用了ticks作为信号处理的回调机制,ticks在速度上远远超过了之前的处理机制。 
    这个变化与“用户ticks”遵循了相同的语义。您可以使用declare() 语句在程序中指定允许发生回调的位置。这使得我们对异步事件处理的开销最小化。
    在编译PHP时 启用pcntl将始终承担这种开销,不论您的脚本中是否真正使用了pcntl。 PHP 4.3.0使用ticks作为信号处理回调机制,这比以前的机制快了很多。
    这个变化与 "用户ticks" 遵循了相同的语义。您可以使用declare() 语句在程序中指定允许发生回调的位置。
    

    demo

    <?php
    class pcntl{
        public function do_reap() {
            echo 'this is over with null' . PHP_EOL;
            exit('this is over');
        }
    
        /**
         * 测试捕获kill信号
         * */
        public function testKill() {
    
            //安装信号处理器 Ctrl + C
            //pcntl_signal(SIGINT, array(&$this,"cron_JIGUANG_push_ctrl_c"));
            //安装信号处理器 kill
            //pcntl_signal(15, array(&$this,"cron_JIGUANG_push_kill"));
    
            //安装信号处理器 Ctrl + C
            pcntl_signal(SIGINT, function(){
                echo "捕获到了 SIGINT 信号" . PHP_EOL;
            });                 //
            //安装信号处理器 kill
            pcntl_signal(15, array(&$this,"do_reap"));
            for($i = 0;$i<30;$i++) {
                echo $i . PHP_EOL;
                sleep(3);
                //调用等待信号的处理器   调用每个通过pcntl_signal() 安装的等待信号的处理器。
                pcntl_signal_dispatch();
            }
        }
    
        /**
         * 注册信号回调不存在方法时处理逻辑
         * */
        public function __call($name, $arguments) {
            $this->doKill($name);
        }
    
    
        /**
         * 添加信号处理程序
         * @param   string      $name       信号标识
         * */
        public function doKill($name) {
            //log
            CronKillLogModel::gi()->add(array('kill_signal'=>$name,'create_time'=>date('Y-m-d H:i:s')));
            exit('this is over');
        }
    }
    >
    
    

    注意:

    这个程序会再执行状态,当我们按下 Ctrl + c 时,就给程序发送了一个 SIGINT 信号,但由于我们自定义了信号处理,所以这时不会结束进程,而是执行信号接收回调函数。

    相关文章

      网友评论

          本文标题:系统编程-信号

          本文链接:https://www.haomeiwen.com/subject/pbltgktx.html