ホームページ >バックエンド開発 >PHPチュートリアル >PHP プロセスの信号処理を 1 つの記事で徹底的に理解する
この記事は、PHP に関する関連知識を提供するもので、主に PHP のプロセス信号処理について詳しく紹介しています。興味のある友達は一緒に見てください。皆様のお役に立てれば幸いです。
PHP ビデオ チュートリアル #]
を中断します。プロセスは別のプロセスにシグナルを送信することができ、例えば子プロセスが終了すると親プロセスにSIGCHLD(シグナル番号17)を送信して通知するため、シグナルがインターバルとして使用されることもあります。プロセス通信メカニズム。 Linux システムでは、通常、プロセスを終了するために kill -9 XXPID を使用します。実際、このコマンドの本質は、プロセスに SIGKILL (シグナル番号 9) を送信することです。フォアグラウンドのプロセスの場合、通常、実行を終了するには Ctrl c ショートカット キーを使用します。このショートカット キーの本質は、現在のプロセスに SIGINT (シグナル番号 2) を送信することであり、このシグナルを受信したときのプロセスのデフォルトの動作は実行を終了することです
信号名 | 信号値 | 信号タイプ | 信号の説明 |
---|---|---|---|
SIGHUP | 1 | プロセスを終了します (端末回線がハングアップします) | このシグナルは、ユーザー端末の接続 (正常または異常) が終了したときに発行されます。 )、通常、端末の制御プロセスが終了すると、同じセッション内の各ジョブが通知されますが、この時点では、それらは制御端末とは関連付けられていません |
2 | プロセスの終了 (プロセスの割り込み) | プログラムの終了 (割り込み、シグナル、ユーザーが INTR 文字 (通常は Ctrl-C、 | |
3 | CORE ファイルを作成してプロセスを終了し、CORE ファイルを生成します | プロセスと CORE ファイルを生成します SIGQUIT は SIGINT に似ています、ただし、その前に QUIT 文字 (通常は Ctrl-、Control が付きます。プロセスは、SIGQUIT を受信して終了するときにコア ファイルを生成します。この意味で、これはプログラム エラー信号 | ## に似ています。 |
8 | CORE ファイルの作成 (浮動小数点例外) | SIGFPE は、浮動小数点演算だけでなく致命的な算術演算エラーが発生した場合に発行されます。エラーだけでなく、オーバーフローや 0 による除算などの他のすべての算術エラーも含まれます | |
9 | プロセスを終了する (プロセスを強制終了する) | SIGKILL は、プログラムの実行を直ちに終了するために使用されます。このシグナルはブロックできず、処理および無視できません。 | ##SIGSEGV |
SIGSEGV は、それ自体に割り当てられていないメモリにアクセスしようとしています、または書き込み権限のないメモリ アドレスにデータを書き込もうとしています |
#SIGALRM | ||
プロセスを終了します (タイマー期限切れ) | SIGALRM クロック タイミング信号 (実際の時刻またはクロック時刻を計算します。アラーム機能はこの信号を使用します) | SIGTERM | |
プロセスを終了する (ソフトウェア終了シグナル) | SIGTERM プログラム終了 (終了、シグナル。SIGKILL とは異なり、このシグナルはブロックされて処理されます。これは通常、プログラムが正常に終了するように要求するために使用されます。シェル コマンド kill は、デフォルトでこのシグナルを生成します。 | #SIGCHLD | |
シグナルを無視します (子プロセスが停止または終了したときに親プロセスに通知します) | SIGCHLD 子プロセスが終了すると、親プロセスはこのシグナルを受け取ります | SIGVTALRM | |
プロセスを終了します (仮想タイマーの期限切れ) | SIGVTALRM 仮想クロック信号。SIGALRM と似ていますが、プロセスが占有する CPU 時間を計算します | SIGIO | |
シグナルを無視します (記述子 I/O で実行できます) | SIGIO ファイル記述子を開始する準備ができています入出力操作 |
2. PHP の信号処理関連関数PHP の pcntl 拡張機能と posix この拡張機能は、信号を操作するためのいくつかのメソッドを提供します (これらの機能を使用したい場合は、最初にこれらの拡張機能をインストールする必要があります) 以下は、このタスクで使用したいくつかのメソッドの詳細な紹介です。 declaredeclare 構造体は、コードの実行命令を設定するために使用されます。宣言の構文は、他のフロー制御構造と似ています。 declare (directive) statement ディレクティブ部分を使用すると、宣言コード セグメントの動作を設定できます。現在、認識される命令は ティックとエンコーディング の 2 つだけです。コード宣言セクションのステートメント部分が実行されます。実行方法と発生する副作用は、ディレクティブ Ticks Tick(クロック サイクル) は、インタプリタが宣言コード セグメント内の N 個の時間指定可能な 低レベル ステートメント を実行するたびに発生するイベントです。N の値は、宣言のディレクティブ部分の Nicks=N で指定します。すべてのステートメントに時間を設定できるわけではありません。通常、条件式とパラメータ式は時刻指定できません。各ティックに表示されるイベントは register_tick_function() で指定されます。各ティックに複数のイベントが表示される可能性があることに注意してください。 詳細については、公式ドキュメントを参照してください: https://www.php.net/manual/zh/control-structurals.declare.php <?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_signalpcntl_signal、信号プロセッサをインストールします pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] ) : bool 関数 pcntl_signal() は、signo で指定された信号の新しい信号プロセッサをインストールします declare(ticks = 1); pcntl_signal(SIGINT,function(){ echo "你按了Ctrl+C".PHP_EOL; }); while(1){ sleep(1);//死循环运行低级语句 } 输出:当按Ctrl+C之后,会输出“你按了Ctrl+C” posix_killposix_kill、プロセスにシグナルを送信します posix_kill ( int $pid , int $sig ) : bool 最初のパラメータはプロセス ID、2 番目のパラメータはプロセス ID です。パラメータ パラメータは送信するシグナルです。 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_dispatchpcntl_signal_dispatch。シグナルを待機しているプロセッサを呼び出します
pcntl_signal_dispatch ( void ) : bool関数 pcntl_signal_dispatch() は、pcntl_signal() によってインストールされたプロセッサを通じて待機中の各シグナルを呼び出します。 <?php echo "安装信号处理器...\n"; pcntl_signal(SIGHUP, function($signo) { echo "信号处理器被调用\n"; }); echo "为自己生成SIGHUP信号...\n"; posix_kill(posix_getpid(), SIGHUP); echo "分发...\n"; pcntl_signal_dispatch(); echo "完成\n"; ?> 输出: 安装信号处理器... 为自己生成SIGHUP信号... 分发... 信号处理器被调用 完成 ##pcntl_async_signals() 非同期信号処理は、ティックなしの非同期信号処理を有効にするために使用されます (これにより、多くの追加オーバーヘッドが発生します)。 (PHP>=7.1)<?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 でセマフォを処理する方法私たちは何を知っているかを知っています。信号を監視するには、declare(ticks=1) と pcntl_signal を組み合わせます。つまり、すべての低レベルの PHP ステートメントで、現在のプロセスに未処理の信号があるかどうかがチェックされます。これは、実際には非常にパフォーマンスを消費します。pcntl_signal の実装原則は、シグナルをトリガーした後、まずシグナルをキューに追加することです。次にPHPのticksコールバック関数にシグナルがあるかどうかを継続的にチェックし、シグナルがある場合は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; } PHP5.3 以降には、pcntl_signal_dispatch 関数があります。現時点では、宣言は必要ありません。ループに関数を追加してシグナルを呼び出して渡すだけです: <?php echo getmypid();//获取当前进程id pcntl_signal(SIGUSR1,function(){ echo "触发信号用户自定义信号1"; }); while(1){ pcntl_signal_dispatch(); sleep(1);//死循环运行低级语句 } PHP の Nicks=1 は、この関数が次の間隔でコールバックされることを意味することは誰もが知っています。 PHP コードの 1 行が実行される時間。実際、ほとんどの場合シグナルは生成されませんが、ticks 関数は常に実行されます。サーバー プログラムが 1 秒間に 1,000 リクエストを受信した場合、各リクエストは平均して 1,000 行の PHP コードを実行することになります。次に、PHP の pcntl_signal により、さらに 1000 * 1000、つまり 100 万回の空の関数呼び出しが発生します。これにより、多くの CPU リソースが無駄になります。より良いアプローチは、ティックを削除し、代わりに pcntl_signal_dispatch を使用してコード ループ内でシグナルを自分で処理することです。 pcntl_signal_dispatch 関数の実装: 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; } } しかし、上記のようなものには、無限ループに入れなければならないという嫌な部分もあります。 PHP7.1以降、非同期シグナルの受信と処理を完了する関数が登場しました。 pcntl_async_signals <?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信号 pcntl_async_signals メソッドを使用すると、無限ループを記述する必要はありません。 监听信号的包: https://github.com/Rain-Life/monitorSignal |
以上がPHP プロセスの信号処理を 1 つの記事で徹底的に理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。