Ubuntu Linux マシンで実行している PHP スクリプトがあります。スクリプトは、関数を使用して複数のプロセスを生成し、pcntl_fork()
関数を使用pcntl_waitpid()
してそれらが強制終了されたことをログに記録します。これらは非常に頻繁に生成されます(私は約 40 ~ 50/秒と見積もっています)が、これらのプロセスはそれぞれすぐに強制終了されます(両方exit()
とposix_kill(${pid}, SIGKILL)
、 無駄に)。スクリプトは数秒間 (場合によっては 10 ~ 30 秒) 正常に動作しますが、必然的に停止し、「子」プロセスの作成を停止します。スクリプトによるマシンのメモリ使用量は増加しませんが、スクリプトが停止すると、Ctrl-C でスクリプトを強制終了するまで、マシンの CPU がゆっくりと上昇します。各プロセスは、テキスト行を解析し、最終的にファイルに保存することを目的としています。テスト目的で、子プロセスが作成されたらすぐに終了しています。あるテストでは、約 1400 のプロセスが正常に開始され、スクリプトがフリーズする前に強制終了されました。
マシンには ulimit があることは理解していますが、同時プロセスの数が制限されていることを読んだと思います。このスクリプトは、子プロセスが作成されるとすぐにそれらを強制終了するため、何が起こっているのか混乱しています。現在の ulimit 構成からの出力は次のulimit -a
とおりです ( )。
コア ファイル サイズ (ブロック、-c) 0 データ セグメント サイズ (キロバイト、-d) 無制限 スケジューリング優先度 (-e) 0 ファイルサイズ (ブロック、-f) 無制限 保留中のシグナル (-i) 29470 最大ロック メモリ (キロバイト、-l) 64 最大メモリ サイズ (キロバイト、-m) 無制限 ファイルを開く (-n) 1024 パイプサイズ (512 バイト、-p) 8 POSIX メッセージ キュー (バイト、-q) 819200 リアルタイム優先度 (-r) 0 スタックサイズ (キロバイト、-s) 8192 CPU 時間 (秒、-t) 無制限 最大ユーザー プロセス (-u) 29470 仮想メモリ (キロバイト、-v) 無制限 ファイルロック (-x) 無制限
スクリプトの実行中に作成されるプロセスの総数を決定する PHP のグローバルな制限はありますか? **これらの子プロセスはすぐに強制終了されることに注意してください。そのため、システム リソースを盗むプロセスが無制限に作成されるという問題ではないと思います。
ソースコードは次のとおりです。
これでフォークを初期化します
$this->process_control->fork(array($this, "${FUNCTION_NAME}"), array(STRING_LINE), false);
プロセス分岐機能。この例では、$callback は適切なクラスで呼び出す関数の名前です。$params は、$callback で指定された関数に渡すパラメーターの配列です。
パブリック関数フォーク ($callback、$params = null、$hang = true) { $this->logger->write_log('log', "fork 関数に入りました!"); // fork の戻り値を評価する スイッチ ($pid = pcntl_fork()) { case -1: // 失敗 $this->logger->write_log('error', "フォークできませんでした!"); 終了 (1); 壊す; case 0: // 子が正常に作成されました $this->logger->write_log('log', "子関数を入力しました!"); $this->logger->write_log('log', 'child ' . posix_getpid() . ' started'); if (empty($callback)) { $this->logger->write_log('warn', "コールバックが空です。何もすることはありません!"); 終了 (1); } if (is_array($callback) && is_array($params)) { if (!call_user_func_array($callback, $params)) { $this->logger->write_log('error', "デーモン化されたプロセスが false を返しました!"); 終了 (1); } そうしないと { 終了 (0); } } そうしないと { if (!call_user_func($callback, $params)) { $this->logger->write_log('error', "デーモン化されたプロセスが false を返しました!"); 終了 (1); } そうしないと { 終了 (0); } } 壊す; デフォルト: // 親 $this->logger->write_log('log', "親関数に入りました!"); if ($ハング!= true) { $this->wait($pid, false); } そうしないと { $this->wait($pid); } 壊す; } } public function wait($p_id, $hang = true) { if ($ハング) { $pid = pcntl_waitpid($p_id, $status); } そうしないと { $pid = pcntl_waitpid($p_id, $status, WNOHANG); } スイッチ($pid) { ケース-1: ケース 0: $this->logger->write_log('log', "child exited"); 壊す; デフォルト: $this->logger->write_log('log', "child $pid exited"); 壊す; } }
テキスト行を実際に処理する関数。テキスト行は JSON オブジェクトです。
public function FUNCTION_NAME($line) { $this->logger->write_log('info', '入力された FUNCTION_NAME 関数'); $start_time = マイクロタイム(真); 試す { # JSON 行の形式が正しくないことを確認します $line_array = json_decode($line, true); if (!isset($line_array)) { throw new Exception('行を正常に処理できませんでした'); } # 内容をディスクに保存 if (!file_put_contents(FILE_NAME, $line, LOCK_EX)) { throw new Exception('ファイルを保存できませんでした'); } $this->logger->write_log('info', 'saved line'); true を返します。 } キャッチ (例外 $e) { $this->logger->write_log('error', $e->getMessage()); $this->logger->write_log('エラー', '------------------------------------ ----------------'); $this->logger->write_log('error', var_export($line, true)); $this->logger->write_log('エラー', '------------------------------------ ----------------'); file_put_contents(ERROR_SRC_FILE, $line, FILE_APPEND); false を返します。 } }
コードが多すぎる場合は申し訳ありませんが、質問があればお知らせください