準備
PHP が単一プロセスで実行されることは誰もが知っていますが、PHP によるマルチ同時実行の処理は、主にサーバーのマルチプロセスまたは PHP-FPM とプロセスの再利用は重要ですが、PHP 複数のプロセスを実装することも、特にバックグラウンドの Cli モードで大量のデータを処理する場合や、バックグラウンドで DEMON
デーモン プロセスを実行する場合に非常に重要です。複数のプロセスの利点は言うまでもありません。
PHP のマルチスレッドについても言及されていますが、プロセス内でのマルチスレッドのリソース共有と割り当ての問題は解決が困難です。 PHP にもマルチスレッド拡張機能 pthreads
がありますが、不安定でスレッドセーフな環境が必要と言われているため、あまり使われていません。
過去に、PHP グループの偉大な達人が、バックグラウンド PHP を進めたいならマルチプロセスを避けなければならないと指導したことがありますが、たまたま社内のデーモン プロセスも PHP を使用しているためです。マルチプロセス、Gu Ge のさまざまな情報と組み合わせた情報とマニュアルを読んだ後、ようやくマルチプロセスを理解し、小さなデモ (Linux システム上で実装) を作成しました。この記事にまとめておきます。間違いや漏れがあれば、 、言及していただきありがとうございます。
PHP マルチプロセスを実装するには、pcntl
と posix
という 2 つの拡張機能が必要ですが、インストール方法についてはここでは説明しません。
php では、pcntl_fork()
を使用して複数のプロセスを作成します (*NIX システムの C 言語プログラミングでは、既存のプロセスは fork 関数を呼び出すことで新しいプロセスを生成します)。フォーク後の新しいプロセスは子プロセスになり、元のプロセスは親プロセスになり、子プロセスは親プロセスのコピーを持ちます。ここで注意してください:
• 子プロセスは、親プロセスとプログラム テキスト セグメントを共有します。
• 子プロセスは、親プロセスのデータ領域、ヒープ、およびスタックのコピーを持っています。共有ではなくコピーです
• 親プロセスと子プロセスはフォーク後もプログラム コードを実行し続けます
#• フォーク後、親プロセスと子プロセスのどちらが実行されるか最初は確認できず、システムのスケジューリングに依存します (信念に依存します)ここでは、子プロセスが親プロセスのデータ領域、ヒープ、およびスタックのコピーを持っていると言われています。ほとんどの実装では、真の完全なコピーではありません。さらに重要なのは、COW (Copy On Write) テクノロジーを使用してストレージ容量を節約していることです。簡単に言うと、親プロセスも子プロセスもこれらのデータ、ヒープ、スタックを変更しない場合、親プロセスと子プロセスは一時的に同じデータ、ヒープ、スタックを共有します。親プロセスまたは子プロセスがデータ、ヒープ、およびスタックを変更しようとした場合にのみ、コピー操作が発生します。これはコピーオンライトと呼ばれます。 pcntl_fork() を呼び出した後、この関数は 2 つの値を返します。親プロセス内の子プロセスのプロセス ID を返し、子プロセス自体の内部では数値 0 を返します。 Apache や fpm 環境では複数のプロセスを適切に実行できないため、php cli 環境でコードを実行する必要があります。サブプロセスの作成
PHP サブプロセスの作成は複数のプロセスの始まりです。pcntl_fork() 関数が必要です。
fork関数の詳細説明
pcntl_fork() # 現在のプロセスの現在位置に分岐(子プロセス)を生成します。この関数が新しい子プロセスを作成した後、子プロセスは親プロセスの現在のコンテキストを継承し、親プロセスと同様に
pcntl_fork() 関数から下位に実行を続けます。ただし、
pcntl_forkが得られます() 戻り値が異なりますので、戻り値を判断することで親プロセスと子プロセスを区別し、親プロセスと子プロセスに異なる論理処理を割り当てることができます。
fork 子プロセス
$ppid = posix_getpid();
$pid = pcntl_fork();
if ($pid == -1) {
throw new Exception('fork child process fail');
} elseif ($pid > 0) {
cli_set_process_title("我是父 process,pid is : {$ppid}.");
sleep(30);
} else {
$cpid = posix_getpid();
cli_set_process_title("我是 {$ppid} 子的 process,我的 process pid is : {$cpid}.");
sleep(30);
}
posix_getpid(): 現在のプロセス id を返します。
cli_set_process_title('プロセス名'): 現在のプロセスにわかりやすい名前を付けます。
この例を実行すると、現在の 2 つの PHP プロセスが表示されます。
www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ ps aux|grep -v grep |grep 我 www 18026 0.5 1.2 204068 25772 pts/0 S+ 14:08 0:00 我是父 process,pid is : 18026. www 18027 0.0 0.3 204068 6640 pts/0 S+ 14:08 0:00 我 18026 子的 process,我的 process pid is : 18027.
コードの最初のセクションでは、プログラムが pcntl_fork() から開始された後、親プロセスと子プロセスがコードの実行を継続します:
$pid = pcntl_fork(); if( $pid > 0 ){ echo "我是父亲".PHP_EOL; } else if( 0 == $pid ) { echo "我是儿子".PHP_EOL; } else { echo "fork失败".PHP_EOL; }
結果:
www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 123.php 我是父亲 我是儿子
2 番目のセクション 子プロセスが親プロセスのデータを共有するのではなくコピーを持つことを示すコード:
// 初始化一个 number变量 数值为1 $number = 1; $pid = pcntl_fork(); if ($pid > 0) { $number += 1; echo "我是父亲,number+1 : { $number }" . PHP_EOL; } else if (0 == $pid) { $number += 2; echo "我是儿子,number+2 : { $number }" . PHP_EOL; } else { echo "fork失败" . PHP_EOL; }
Result
www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 1234.php 我是父亲,number+1 : { 2 } 我是儿子,number+2 : { 3 }
以上がPHP7の複数プロセスに関する予備調査の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。