ネットワーク – ウェブサーバはどのようにIPアドレスを「聞く」のか、割り込みやポーリングは?

embedded networking webserver

ウェブサーバの下っ端を理解しようとしています。私は、サーバ、例えばApacheは、新しい要求のために継続的にポーリングしているか、またはそれが何らかの種類の割り込みシステムによって動作する場合、疑問に思っています。割り込みだとしたら、何が割り込みの火付け役になっているのか、ネットワークカードのドライバなのか

  88  user2202911  2014-11-09


ベストアンサー

簡単に言うと、ある種の割り込みシステムです。基本的には、新しいデータを待っている間にスリープ(ブロック)することを意味するブロッキングI/Oを使用します

  1. サーバはリスニングソケットを作成し、新しい接続を待つ間ブロックします。この間、カーネルはプロセスを割り込み可能なスリープ状態にし、他のプロセスを実行します。これは重要なポイントです。プロセスを継続的にポーリングさせると CPU を無駄にします。カーネルは、やるべきことがあるまでプロセスをブロックすることで、システムリソースをより効率的に使うことができます

  2. ネットワーク上に新しいデータが到着すると、ネットワークカードは割り込みを発行します

  3. ネットワークカードからの割り込みがあると、カーネルはネットワークカードドライバを介して、ネットワークカードから新しいデータを読み込んでメモリに保存します(これは迅速に行われなければならず、一般的には割り込みハンドラの中で処理されます)。(これは素早く行わなければならず、一般的には割り込みハンドラの中で処理されます)

  4. カーネルは新たに到着したデータを処理し、ソケットに関連付けます。そのソケット上でブロックしているプロセスは runnable とマークされます。このプロセスはすぐに実行されるとは限りません (カーネルは他のプロセスを実行することを決定するかもしれません)

  5. 余裕をもって、カーネルはブロックされたウェブサーバプロセスを起動します。(これで実行可能になったので)

  6. ウェブサーバプロセスは、時間が経過していないかのように実行を続けます。ブロッキングシステムコールが戻り、新しいデータを処理します。それから…ステップ1に進みます

182  Greg Bowser  2014-11-09


下」のディテールがかなり多いですね

まず、カーネルがプロセスのリストを持っていて、いつでもこれらのプロセスのいくつかが実行されていて、いくつかは実行されていないと考えてください。カーネルは実行中の各プロセスに CPU 時間の一部を与え、それを中断して次のプロセスに移動します。実行可能なプロセスがない場合、カーネルはおそらく HLT のような命令を CPU に発行し、ハードウェア割り込みが発生するまで CPU を一時停止させます

サーバのどこかに、Apache が以前にオープンしたソケットの system call that says “give me something to do”. There are two broad categories of ways this can be done. In the case of Apache, it calls accept があります。カーネルは接続試行のキューを保持しており、TCP SYN を受信するたびにキューに追加しています。カーネルが TCP SYN が受信されたことをどのようにして知るかはデバイスドライバに依存します

accept はカーネルに次の接続開始を返すように要求します。キューが空でなければ、accept はすぐに戻ります。キューが空であれば、そのプロセス (Apache) は実行中のプロセスのリストから削除されます。後になって接続が開始されると、プロセスは再開されます。これは “ブロッキング” と呼ばれるもので、それを呼んでいるプロセスにとっては、 accept() は結果が出るまで返さない関数のように見えるので、今からしばらくの間は何もできません。その間、プロセスは何もすることができません

accept が返ってくると、Apache は誰かが接続を開始しようとしていることを知っています。そして、fork を呼び出して、Apache のプロセスを二つの同一のプロセスに分割します。これらのプロセスのうちの一つは HTTP リクエストを処理し、もう一つは次の接続を得るために accept を再び呼び出します。このように、accept を呼び出してサブプロセスを生成する以外は何もしないマスタープロセスが常に存在し、各リクエストに対して一つのサブプロセスが存在します

これは単純化したものです: プロセスの代わりにスレッドでこれを行うことも可能ですし、リクエストを受け取ったときにワーカープロセスを準備できるように fork をあらかじめ用意しておくことも可能なので、起動時のオーバーヘッドを減らすことができます。Apache がどのように設定されているかにもよりますが、これらのいずれかを行うことができます

これがやり方の最初の大まかな分類で、ソケットで動作するacceptreadwriteのようなシステムコールが、何か返すものがあるまでプロセスを一時停止させるため、ブロッキングIOと呼ばれています

他の大まかな方法として、ノンブロッキング、イベントベース、asynchronous IO. This is implemented with system calls like selectepoll と呼ばれるものがあります。これらはそれぞれ同じことをします: ソケット (または一般的にはファイルディスクリプタ) のリストとそれを使って何をしたいかを与え、カーネルはそれらのいずれかを実行する準備が整うまでブロックします

このモデルでは、カーネルに(epollを使って)「ポート80に新しい接続があったら教えてくれ」とか「私が開いている9471の他の接続のどれかに新しいデータがあったら教えてくれ」と言うかもしれません。epoll はこれらのうちのどれかが準備が整うまでブロックし、それを実行します。そして、それを繰り返します。acceptreadwrite のようなシステムコールはブロックされませんが、これは epoll が「準備ができたのでブロックする理由がない」と言っていることと、ソケットやファイルを開くときにノンブロッキングモードにしたいと指定しているため、これらのコールはブロックされる代わりに EWOULDBLOCK で失敗します

このモデルの利点は、1つのプロセスしか必要としないことです。つまり、リクエストごとにスタックやカーネル構造体を割り当てる必要がないということです。NginxHAProxy はこのモデルを使用しています

9  Phil Frost  2014-11-12


タイトルとURLをコピーしました