2012-04-19 8 views
0

のために呼び出された後に何が起こるか:は読み取りがLinuxのソケット実際に読んで呼び出した後に何が起こる

n = read(fd, buf, try_read_size); 

ここでfdはTCPソケット記述子です。 bufはバッファです。 try_read_sizeは、プログラムが読み取ろうとするバイト数です。

これは最終的にカーネルへのシステムコールを呼び出すかもしれないと思います。しかし、誰かがいくつかの詳細を提供できますか? glibcやカーネルソースのソースコードの実装について教えてください。

+1

カーネルの詳細はSO答える短いためにあまりにも複雑です。あなたはそれを自分でチェックしてみませんか? –

+0

@KarolyHorvath私は試みたが、完全に迷った。詳細を知るための方向性や提案はありますか?私はそれを高く評価します。 – ericzma

+0

Linuxのカーネルソースからfs/read_write.cを読み込み、何が起きているのかを見てください。 – strkol

答えて

4

高レベルの観点から、これは何が起こるかである:

  • をglibcのによって提供されるラッパー関数は、ラッパー関数がシステムコール番号をレジスタにスタックに渡されたパラメータを置き、設定
  • 呼ばれその目的のために専用のレジスタ(x86の上に例えばEAX)
  • ラッパー関数は、トラップまたは同等の命令を実行する(例えば、SYSENTER)
  • でリング0へのCPUスイッチ、トラップハンドラは
  • 呼び出され
  • トラップハンドラは、システムコール番号の妥当性をチェックし、ジャンプテーブル内でカーネル関数にルックアップします。
  • それぞれのカーネル機能は、引数が有効かどうかをチェックします。範囲bufbuf+try_read_sizeは、アクセス可能なメモリページを指し、fdは実際にはファイル記述子です)。何か問題がある場合は、負のエラーコード(たとえば、-EFAULT)が生成され、CPUがユーザーモードに戻り、呼び出しがラッパーに戻ります。
  • 別の機能は、ファイル記述子のタイプに応じて呼び出された(ソケットあなたのケースでは、しかし、1つは、ブロックデバイスまたはprocエントリ以上のエキゾチックな何かから読むことができる)
  • ソケットの入力バッファがチェックされている:
    • バッファにデータがある場合、min(available, try_read_size)bufにコピーされ、その額が返却コードレジスタ(x86ではEAX)に書き込まれ、CPUはユーザーモードに戻り、呼び出しはラッパーに戻ります。
    • 接続が閉じられた場合、入力バッファはゼロ戻りコード・レジスタに書き込まれ、
      • 空である場合、CPUは、接続した場合、バックユーザモードおよびラッパー
      • の呼び出しが戻るように切り替えられます
        • を閉じられいないソケットが非ブロッキングされている場合はマイナスのエラーコード(-EAGAIN)がリターンコードレジスタに書き込まれ、CPUは、ユーザモード及びラッパーへのコールリターンにスイッチバックされます。
        • ソケット戻り値が負であるかどうかではない非ブロッキング
  • ラッパー関数をチェックする(エラー)である場合、プロセスは中断されます。
    • 正または0の場合、値を返します。
    • 負の場合は、それが負の値(エラーが報告される)とリターンをerrnoに設定し-1
+0

+1、非常に良い。プロセスが中断された場合、少なくとも1バイトのデータまたはFINが受信されるか、ソケットにエラーがポストされるまでブロックされ、この中に含まれる最も外側の箇条書きポイントが再開されます。 – EJP