PHPマルチプロセスの開発を手がける

19019 ワード

私达はすべて仕事が多すぎて一人でやりきれないことを知っていて、多くの人を探して手伝いに行って、みんなは仕事の量を分けて、事もできるのが少し速くて、しかし欠点があって、すべての人はすべていくつかの重複の事をしなければならなくて、例えばすべてドキュメントを見て、需要を理解して、やっとすることができて、もし一人ならば、するのが遅いですが、しかし、占有する資源も相対的に少ない.マルチプロセスの使用のように、バランスも必要です.
1.マルチプロセスを使用するシーン
メールを送信したり、ファイルを処理したり、独立した個体を一括処理したりするなど、繰り返して時間がかかる操作があります.例えば、ブロガーが今回使用するシーンは、各アカウントのエンティティが独立しており、比較的スケールが大きく、処理ロジックにはネットワーク通信消費量とデータベースクエリーが多いエンティティ情報を一括同期する操作です.スクリプトが頻繁にカードマスターを実行するようになります.カードポイントは主に処理が遅く、同時に、機械の負荷が高く、プロセスが分けられるタイムスライスも多くない.
PHPのマルチプロセスとコヒーレンスは同じ概念ではなく,1つはプロセスベースであり,もう1つはスレッドベースである.オペレーティングシステムの最小スケジューリング単位はプロセスであり、1つのプロセスに少なくとも1つのスレッドを含めることができることを知っています.プロセス間は互いに隔離されており、プロセス間の通信はパイプ、共有メモリ、メッセージキューなどの特殊な方法に基づいているだけで、スレッドは共有プロセス資源であるため、通信はそんなに面倒ではないが、スレッドの安全問題はまた弊害であり、資源は共有されており、みんながそれを動かす権限があるため、問題が発生しやすい.だから反発ロックが必要で、マルチスレッド開発はマルチプロセス開発よりも複雑になります.後でswooleに関するいくつかの文章を書いたとき、私たちはまた議論します.
2.phpマルチプロセスの使用方法
c言語はfork関数に基づいてサブプロセスの作成を行うことを知っている.Linuxもこの原理に基づいており、すべてのLinuxプロセス(0番プロセスを除く)は0番プロセスforkによって来ており、この0番プロセスはすべてのプロセスの始祖である.
まず、peclがインストールされていることを確認し、linux php-cliモードでコードが実行されていることを確認してください.
PHPもクラスC関数を提供しており、今回の学習で使用する関数は以下の通りです.
2.1サブプロセスの作成
pcntl_fork ( void ) : int

成功すると、親プロセス実行スレッド内に生成された子プロセスのPIDが返され、子プロセス実行スレッド内に0が返されます.失敗すると、親プロセスコンテキストで-1が返され、サブプロセスは作成されず、PHPエラーが発生します.
ドキュメント栗:


$pid = pcntl_fork();
//               
if ($pid == -1) {
    //    :          -1.
     die('could not fork');
} else if ($pid) {
     //          ,             
     pcntl_wait($status); //       ,           。
} else {
     //      $pid 0,              。
}

?>

大まかに説明すると、この関数はPHPでサブプロセスを作成するために使用され、成功した戻り値がサブプロセスのプロセスIDであれば、-1を返すと、サブプロセスの作成に失敗し、0を返すと、サブプロセスの作成に成功したことを示しますが、このとき実行されるのは親プロセスのコードで、プロセス間は独立しており、どのプロセスが先に実行されるかを制御することはできません.cpuのタイムスライスが分割されると、ブロックされたコードを使用して指定された順序の実行を強制しない限り、実行されます.したがって、この場合、戻り値を使用して、現在実行されている親プロセスコードかサブプロセスコードかを判断できます.
2.2現在のプロセスIDの取得
getmypid ( void ) : int

関数は、現在のコード実行プロセスのプロセスIDを直接返します.
2.3傍受プロセス
pcntl_waitpid ( int $pid , int &$status [, int $options = 0 [, array &$rusage ]] ) : int


pcntl_waitpid()は、終了したサブプロセス番号を返し、エラーが発生した場合は-1を返し、WNOHANGがoption(wait 3が利用可能なシステム)として提供され、サブプロセスが使用できない場合は0を返します.
これは、サブプロセスが使用を終了するかどうかを監視するために使用されます.ここでは、関数の使用を自分で検討する方法の1つを使用しています.
2.4より完璧な栗を書く


namespace Test;

class Test
{
    /** @var int     10     */
    protected $processNums;

    /** @var int        */
    const CHILD_RUN = 0;

    /** @var int    */
    const FORK_ERROR = -1;


    public function __construct(int $processNums = 10)
    {
        $this->processNums = $processNums;
    }

    public function run()
    {

        for ($i = 1; $i <= $this->processNums; $i++) { //           ,    1       
            $pid = pcntl_fork();
            $this->dispatchInfo("    :" . getmypid() . ' fork    :' . $pid);
            switch ($pid) {
                case self::FORK_ERROR:
                    $this->dispatchInfo('       ');
                    break;
                case self::CHILD_RUN:
                    //   
                    $this->dispatchInfo("     :" . getmypid() . ' ' . "         ");
                    //           
                    exit(0);//       !
                    break;
                default:
                    //       
                    $this->dispatchInfo("    :" . getmypid() . ' ' . "      {$i}    {$pid}");
                    $childPids[] = $pid;
                    break;
            }
        }

        while (count($childPids) > 0) {
            foreach ($childPids as $key => $pid) {
                $res = pcntl_waitpid($pid, $status, WNOHANG);//      ,           
                if ($res == -1 || $res > 0) { //      ,                     
                    $this->dispatchInfo("      {$pid}  ...");
                    unset($childPids[$key]);//         
                }
            }

            if (count($childPids) == 0) { //      
                break;
            }
        }
        $this->dispatchInfo('      ,     ');
    }

    protected function dispatchInfo(string $info)
    {
        echo date("Y-m-d H:i:s") . '  ' . $info . PHP_EOL;
    }

}

3.ゾンビプロセスと孤児プロセスの発生
サブプロセスの終了と親プロセスの実行は、親プロセスがいつ終了するかを予測できない非同期プロセスです.プロセスが完了すると、親プロセスはwait()またはwaitpid()システム呼び出しを呼び出してサブプロセスの終了状態を取得する必要があります.そして、このようにして対応するリソースを回収する.
ここでは、この2つのプロセスの発生と危害について説明します.
3.1孤児プロセス
私たちは知っていて、すべてのユーザー状態のプロセスはすべてそのお父さんから生まれて、もしお父さんが死んだら、それは孤児になりました.孤児になると何か問題がありますか?
実は大丈夫です.養子縁組に来る人がいるので、initプロセス(1番プロセス)というプロセスがあります.それは良い人で、孤児を養子縁組するプロセスで、これらの孤児が正寝できるようにしています.そのため、本質的には、父プロセスが殺されても、システムに大きな影響を与えることはありません.
3.2ゾンビプロセス
ゾンビは、恐ろしい存在で、死なないで、死なないで場所を占めて、地球はこんなに大きくて、無限の容量がありません.ゾンビプロセスはどのような状況で発生しますか?
死神ストです.ここの死神は実は父のプロセスです.サブプロセスが実行されると、プロセス識別子が残り、親プロセスが回収されるのを待っています.親プロセスが回収されていない場合、このプロセス識別子(プロセスID)はずっと占有されます.例えば、トイレが終わったらドアを開けず、他の人に使用されません.
孤児プロセスとゾンビプロセスの発生原因を区別するために、サブプロセスはexitの後、親プロセスは、サブプロセスのプロセスフラグ、すなわち前のpcntl_をアクティブに受信して解放すべきであると考えることができる.waitpid関数は、親プロセスによってサブプロセスを作成しても、自発的に解放しなければ、ゾンビプロセスは必然的に発生します.親プロセスと子プロセスは正常に終了しますが、子プロセスのプロセス識別子はシステムによって解放されません.
それからもう一つの状況を考えてみましょう.親プロセスがkillに落ちて、何が起こるかを考えてみましょう.私たちは前に親プロセスがないと言っていましたが、子プロセスは孤児プロセスになり、引き継がれます.親プロセスが停止しているが、サブプロセスがまだ終了していない場合、彼らは孤児プロセスです.
PS:マルチプロセスは時々使いやすいが、いくつかの弊害もあり、ここでも簡単に解読する方法の一つにすぎない.プロセス通信などの問題はありません.実際に考えなければならないことはたくさんありますが、適切な場面で適切に使ってほしいです.決して乱用してはいけない.