私はApacheのMPMプリフォークサーバーでモデル化されたいくつかのPythonコードに取り組んでいます。私はネットワークプログラマーというよりもアプリケーションプログラマーであり、スティーブンスを読んでから10年が経ちました。そのため、コードの理解に慣れようとしています。
Sander Temmeによる、Apacheのプリフォークコードがどのように機能するかについての簡単な説明を見つけました。
通常rootとして実行される親プロセスは、ソケット(通常はポート80または443)にバインドします。ソケットのオープンファイル記述子を継承する子を生成し、uidとgidを非特権ユーザーとグループに変更します。子は、リスナーファイル記述子のポーリングセットを作成し(複数のリスナーがある場合)、その上でのアクティビティを監視します。アクティビティが見つかった場合、子はアクティブなソケットでaccept()を呼び出し、接続を処理します。それが完了すると、ポーリングセット(またはリスナーファイル記述子)の監視に戻ります。
複数の子がアクティブであり、それらはすべて同じソケットファイル記述子を継承しているため、同じポーリングセットを監視します。ミューテックスを受け入れると、実際にポーリングセットを監視できるのは1人の子だけになり、アクティブなソケットが見つかると、ミューテックスのロックが解除され、次の子がポーリングセットの監視を開始できるようになります。リスナーが1つしかない場合、そのaccept mutexは使用されず、すべての子がaccept()でハングします。
これは私が見ているコードの動作とほぼ同じですが、いくつかのことを理解していません。
1)「子供」と「リスナー」の違いは何ですか?私が見ているコードには、それぞれの子がリスナーであると思いましたが、Temmeの説明では、「単一のリスナー」と「子」が存在する可能性があります。子供にはいつ複数のリスナーがいますか?
2)(1に関連)これはプロセスごとのミューテックスですか、それともシステムミューテックスですか?さらに言えば、なぜミューテックスがあるのですか?accept(2)は、すべてのリスナーにわたって独自のミューテックスを実行しませんか?私の調査によると、ミューテックスが必要であり、ミューテックスはシステム全体に存在する必要があります。(群れ、セマフォなど)
Temmeは続けて次のように述べています。
子供は、最後にリクエストを処理したときに共有メモリ領域(スコアボード)に記録します。MaxSpareServersを満たすために、アイドル状態の子が親プロセスによって強制終了される場合があります。アイドル状態の子が少なすぎる場合、親はMinSpareServersを満たすために子を生成します。
3)この実装(できればPython)に適したリファレンスコードはありますか?PerlのNet::Server :: Preforkを見つけました。これは、スコアボードに共有メモリの代わりにパイプを使用します。ランダル・シュワルツの記事を見つけました。これは、プリフォークのみを実行し、スコアボードは実行しません。
Perl Cookbookのpre-forkの例には、selectに関するロックはありません。また、Chris SiebenmannのPythonの例では、Apacheに基づいていますが、共有メモリではなくスコアボードにペアのソケットを使用し、コントロールにソケットを使用しています。与えられた子を'a'cceptに制御します。これは、Apacheの説明とはまったく一致しません。