Nginxの資料を読みながら、単一のソケットからの着信接続を受け入れる2つの伝統的な方法の1つが次のようになることがわかりました。
単一ポートで実行されるマルチスレッド・サーバーで使用される2番目の従来のアプローチは次のとおりです。すべてのスレッド(またはプロセス)を所有します。
accept()
次の形式の単純なイベントループでは、単一のリスニングソケットへの呼び出しが行われます。while (1) { new_fd = accept(...); process_connection(new_fd); }
それから、Nginxもこのアプローチを使用しているようです。
示されているよう
SO_REUSEPORT
にオプションが有効になっていない場合、単一の受信ソケットはワーカースレッドに着信接続を通知し、各ワーカースレッドは接続を取得しようとします。
から引用NGINXバージョン1.9.1のソケットシャーディング:
アジンアここオープンソースアプリケーションアーキテクチャ(2巻):nginxaccept
、次のキーワードでページを検索してください。
前述のように、nginxは各接続に対してプロセスやスレッドを生成しません。代わりに、ワーカープロセスは、共有された「受信」ソケットからの新しい要求を受け入れ、各ワーカープロセス内で効率的な実行ループを実行して、ワーカープロセスごとに数千の接続を処理します。nginxには専用の定足数やワーカーへの接続割り当てはありません。これはオペレーティングシステムのカーネルメカニズムによって実行されます。
だから本当にショックを受けました。誰も私にプロセスやスレッドにわたってリスニングソケットを受け入れるのは大丈夫で、結果が良くないと言わなかったからです。競争条件。
なぜなら、共有資源を活用すれば、最初に浮かび上がるのが」この関数呼び出しはスレッドセーフですか?「?だからグーグルをして、StackOverflowで関連する質問を見つけました。
許可された回答はもう一度この振る舞いを示していますが、参照をまったく提供しておらず、コメントの下の人々はまだ公式文書の定義について議論しています。
thread-safe
その時点ではマルチスレッドとなっており、与えられた属性が十分ではないと思いました。またはプロセス accept
シングルリスニングソケットから。私にとってはこれより強力なものが必要です。
だから本を読みに来ました。Linuxプログラミングインターフェース、存在する§5.1原子性と競争条件、それは次のように書く:
アトミックは、システムコールの操作について議論するときに引き続き遭遇する概念です。様々なシステムコール操作が原子的に行われる。私たちが意味するのは、カーネルが他のプロセスやスレッドの中断なしに作業のすべてのステップが完了することを保証することです。
原子性は、特定のタスクを正常に完了するために重要です。特に、これは競争条件(レースリスクとも呼ばれる)を避けるのに役立ちます。競合状態は、共有リソースで実行されている2つのプロセス(またはスレッド)が、プロセスがCPUにアクセスする相対的な順序に従って予期しない方法で依存する結果を生成する状況です。
だから私が必要とする言葉/属性は大気または原子性。
だから私の質問は次のようになります
複数のプロセスやスレッドでリスニングソケットを受け入れることがアトミックタスクであると言う権威ある場所はありますか?
数時間検索しても、オンラインで参考資料が見つかりません。
答え1
https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
accept()
「非同期信号安全」機能としてリストされます。全ての非同期信号安全関数がスレッドセーフであることを以下に説明する。ロック解除されたstdio関数などのスレッドセーフのために、いくつかの特定の例外がリストされていますaccept()
。いいえ話す。
ここではaccept
システムコールであることに注意してください。カーネルがスレッドセーフではないという意味なので、システムコールがスレッドセーフではないということは言いません!
カーネルはスレッドセーフである必要があるため、システムコールもスレッドセーフでなければなりません。