ホームページ > バックエンド開発 > PHPチュートリアル > PHP がプロセス信号を処理する方法 (例付き)

PHP がプロセス信号を処理する方法 (例付き)

不言
リリース: 2023-04-04 08:26:02
転載
2606 人が閲覧しました

この記事の内容は、PHP によるプロセス信号の処理方法 (例付き) に関するものであり、一定の参考価値があります。必要な友人は参考にしていただければ幸いです。

php にはプロセス制御関数 PCNTL のセットがあり、これにより PHP は子プロセスを作成し、exec 関数を使用してプログラムを実行し、c のような *nix システムのシグナルを処理できるようになります。

注: pcntl 拡張機能は、cli/cgi モードでのみ使用できます。 mod_php および php-fpm では使用できません。予期しない結果が生じる可能性があるため、この関数セットを Web サーバー環境では使用しないでください。さらに、Windows は非 Unix ライクなシステムなので、これらの機能はありません。

PCNTL は、シグナル ハンドル コールバック メカニズムとしてティックを使用します。これにより、非同期イベントを処理する際の負荷を最小限に抑えることができます。ダニとは何ですか? Tick は、インタープリタがコードセグメント内の N 個の低レベルステートメントを実行するたびに発生するイベントであり、このコードセグメントは宣言によって指定する必要があります。

以下は、SIGALRM シグナルを 5 秒ごとに送信し、signal_handler 関数で取得し、「Caught SIGALRM」を出力する例です。

<?php   
        declare(ticks = 1);   
      
        function signal_handler($signal) {   
            print "Caught SIGALRM/n";   
            pcntl_alarm(5);   
        }   
      
        pcntl_signal(SIGALRM, "signal_handler", true);   
        pcntl_alarm(5);   
      
        while(true){

        }
      
    ?>
ログイン後にコピー

実際、公式の pcntl_signal は非常に貧弱です。主な理由は、PHP 関数をオペレーティング システムのシグナル設定に直接登録できないため、pcntl シグナルはティック メカニズムに依存する必要があるためです。 pcntl_signal の実装原則は、シグナルをトリガーした後、まずシグナルをキューに追加することです。次にPHPのticksコールバック関数にシグナルがあるかどうかを継続的にチェックし、シグナルがある場合はPHPで指定されたコールバック関数を実行し、シグナルがない場合は関数から抜け出します。 ticks=1 は、PHP コードの行が実行されるたびにこの関数がコールバックされることを意味します。実際、ほとんどの場合シグナルは生成されませんが、ticks 関数は常に実行されます。 より良いアプローチは、ティックを削除し、代わりに pcntl_signal_dispatch を使用してコード ループ内でシグナルを自分で処理することです。

#pcntl_signal_dispatch の実装
<?php
// 定义一个处理器,接收到SIGINT信号后只输出一行信息
function signalHandler($signo) {
    switch ($signo) {
        case SIGUSR1: echo "SIGUSR1\n"; break;
        case SIGUSR2: echo "SIGUSR2\n"; break;
        default:      echo "unknow";    break;
    }
}

//安装信号触发器器
pcntl_signal(SIGINT, &#39;signalHandler&#39;);
while (true) {
    sleep(1);
    posix_kill(posix_getpid(), SIGUSR1);///向当前进程发送SIGUSR1信号
    pcntl_signal_dispatch(); //接收到信号时,调用注册的signalHandler()
}
ログイン後にコピー

PCNTL 関数:

信号処理
int pcntl_alarm ( int $seconds )
ログイン後にコピー

$秒秒後に SIGALRM シグナルを送信するカウンターを設定します

bool pcntl_signal(int $signo ,callback $handler [,bool $restart_syscalls=true])
ログイン後にコピー

$signo がシグナルを処理するためのコールバック関数を設定します

最初のパラメーターはシグナル番号です

2 番目のパラメーターは、シグナルの発生時にコールバックされる PHP 関数です。 3 番目のパラメータは、再起動するかどうか、およびこの信号を再登録するかどうかです。このパラメータが false の場合、この信号は 1 回だけ登録され、処理されます。

注:

pcntl_alarm() を呼び出すたびに、以前に設定されたアラーム信号と sleep() 関数がキャンセルされます。

次は、SIGALRM シグナルを 5 秒ごとに送信し、signal_handler 関数で取得して、「Caught SIGALRM」を出力する例です。

<?php   
        declare(ticks = 1);   
      
        function signal_handler($signal) {   
            print "Caught SIGALRM/n";   
            pcntl_alarm(5);   
        }   
      
        pcntl_signal(SIGALRM, "signal_handler", true);   
        pcntl_alarm(5);   
      
        for(;;) {   
        }   
      
    ?>
ログイン後にコピー

実行プログラム
void pcntl_exec ( string $path [, array $args [, array $envs ]] )
ログイン後にコピー

c の exec ファミリ関数と同様に、現在のプロセス空間で指定されたプログラムを実行します。いわゆるカレントスペースとは、指定されたプログラムのコードがロードされ、現在のプロセスを上書きするスペースであり、プログラムの実行後にプロセスが終了します。

<?php   
    $dir = &#39;/home/test/&#39;;   
    $cmd = &#39;ls&#39;;   
    $option = &#39;-l&#39;;   
    $pathtobin = &#39;/bin/ls&#39;;   
      
    $arg = array($cmd, $option, $dir);   
      
    pcntl_exec($pathtobin, $arg);   
    echo &#39;123&#39;;    //不会执行到该行   
    ?>
ログイン後にコピー

プロセスの作成
int pcntl_fork ( void ) 为当前进程创建一个子进程
int pcntl_wait ( int &$status [, int $options ] ) 阻塞当前进程,只到当前进程的一个子进程退出或者收到一个结束当前进程的信号。 
int pcntl_waitpid ( int $pid , int &$status [, int $options ] ) 功能同pcntl_wait,区别为waitpid为等待指定pid的子进程。当pid为-1时pcntl_waitpid与pcntl_wait一样。
ログイン後にコピー

子プロセスのステータス情報は、pcntl_wait および pcntl_waitpid の 2 つの関数の $status に保存されます。このパラメータは、pcntl_wifexited および pcntl_wifexited に使用できます。 pcntl_wifstopped.、pcntl_wifsignaled、pcntl_wexitstatus、pcntl_wtermsig、pcntl_wstopsig、pcntl_waitpid 関数。

<?php   
    $pid = pcntl_fork();   
    if($pid) { 
        pcntl_wait($status);   
        $id = getmypid();   
        echo "parent process,pid {$id}, child pid {$pid}/n";   
    } else {   
        $id = getmypid();   
        echo "child process,pid {$id}/n";   
        sleep(2);   
    }   
    ?>
ログイン後にコピー

子プロセスは、子プロセスなどの単語を出力した後、終了する前に 2 秒間スリープしますが、親プロセスは、子プロセスが終了するまでブロックしてから実行を継続します。

プロセスの優先度
int pcntl_getpriority ([ int $pid [, int $process_identifier ]] ) 取得进程的优先级,即nice值,默认为0。不同的系统类型以及内核版本下 优先级可能不同(手册中为-20到20)
bool pcntl_setpriority ( int $priority [, int $pid [, int $process_identifier ]] ) 设置进程的优先级
ログイン後にコピー

以上がPHP がプロセス信号を処理する方法 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:cnblogs.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート