read/writeデータ読み書き伝送方式
2925 ワード
前言
筆者は標準I/O(キャッシュI/O)を解説するブログを書くつもりだったが、すでに同じ仕事をしていて、仕事の質が優れているネットユーザーがいることに気づき、転載した.
原文アドレスhttp://lenky.info/archives/2012/08/1856
本文
システム呼び出し関数read()/write()は、データの頻繁な読み書きをパフォーマンスのボトルネックとしない多くのアプリケーションで関数read()/write()が消費する実行時間は無視できるため、通常最も多くのデータ読み書き方式で使用されています.しかし、それらの内在的な具体的な実現と実行効率はいったいどうなっているのだろうか.以下、詳細な分析を行います.関数read()/write()はヘッダファイルunistdに定義されます.h内、原型は以下の通りである.
ここでは、関数read()/write()のソースコードを説明するつもりはありません.その実行手順を簡単に説明します.主な呼び出し関係は次の図に示します.
我々のサーバプログラム、例えばnginxがread()/write()データの読み書き伝送方式を採用する場合、あるクライアントが「GET/index.html HTTP/1.1」要求を送信と、nginxはサイトのルートディレクトリに格納indexを必要とする.htmテキストファイルは応答データとしてクライアントに送信される.mmap()が有効でない場合、nginxがこの応答データの送信を完了するには、まず関数read()を用いてindexを2ステップ必要とする.htmテキストファイルデータはメモリに読み込まれ、関数write()を使用してメモリに読み込まれた最初のステップのデータを接続スリーブインタフェース記述子に書き込んで応答データの送信を完了します.
上の図に示すように、nginxアプリケーションは、read()/write()データの読み書き伝送方式で応答データの送信を完了するには、合計4回のコンテキスト切替と4回のデータコピー(すなわち、1回のread()/write()と仮定するindexを必要とする.htmテキストファイルデータの送信が完了した場合、一度だけではない場合、切り替えとコピーの回数が増える)、これらの切り替えとコピープロセスは必要ではないでしょうか.答えは否定的だ.例えば、mmap()が有効な場合には、一度のデータコピーを減らすことができ、システム呼び出しmmap()によりテキストファイルindexを呼び出す.htmデータをカーネルキャッシュ領域にコピーし、コピーマッピングターゲットアドレスの開始値をnginxアプリケーションに返すのは、nginxアプリケーションがこのカーネルキャッシュ領域のマッピング開始アドレスを有し、このカーネルキャッシュ領域(システム呼び出しmmap()実装の結果)を共有できるためである.カーネルBufferからユーザーBuffer、Socket Bufferへのコピーは、カーネルBufferからSocket Bufferへの直接コピーになります.
筆者は標準I/O(キャッシュI/O)を解説するブログを書くつもりだったが、すでに同じ仕事をしていて、仕事の質が優れているネットユーザーがいることに気づき、転載した.
原文アドレスhttp://lenky.info/archives/2012/08/1856
本文
システム呼び出し関数read()/write()は、データの頻繁な読み書きをパフォーマンスのボトルネックとしない多くのアプリケーションで関数read()/write()が消費する実行時間は無視できるため、通常最も多くのデータ読み書き方式で使用されています.しかし、それらの内在的な具体的な実現と実行効率はいったいどうなっているのだろうか.以下、詳細な分析を行います.関数read()/write()はヘッダファイルunistdに定義されます.h内、原型は以下の通りである.
#include <unistd.h>
ssize_t read(int fildes, void *buf, size_t nbyte);
ssize_t write(int fildes, const void *buf, size_t nbyte);
ここでは、関数read()/write()のソースコードを説明するつもりはありません.その実行手順を簡単に説明します.主な呼び出し関係は次の図に示します.
我々のサーバプログラム、例えばnginxがread()/write()データの読み書き伝送方式を採用する場合、あるクライアントが「GET/index.html HTTP/1.1」要求を送信と、nginxはサイトのルートディレクトリに格納indexを必要とする.htmテキストファイルは応答データとしてクライアントに送信される.mmap()が有効でない場合、nginxがこの応答データの送信を完了するには、まず関数read()を用いてindexを2ステップ必要とする.htmテキストファイルデータはメモリに読み込まれ、関数write()を使用してメモリに読み込まれた最初のステップのデータを接続スリーブインタフェース記述子に書き込んで応答データの送信を完了します.
上の図に示すように、nginxアプリケーションは、read()/write()データの読み書き伝送方式で応答データの送信を完了するには、合計4回のコンテキスト切替と4回のデータコピー(すなわち、1回のread()/write()と仮定するindexを必要とする.htmテキストファイルデータの送信が完了した場合、一度だけではない場合、切り替えとコピーの回数が増える)、これらの切り替えとコピープロセスは必要ではないでしょうか.答えは否定的だ.例えば、mmap()が有効な場合には、一度のデータコピーを減らすことができ、システム呼び出しmmap()によりテキストファイルindexを呼び出す.htmデータをカーネルキャッシュ領域にコピーし、コピーマッピングターゲットアドレスの開始値をnginxアプリケーションに返すのは、nginxアプリケーションがこのカーネルキャッシュ領域のマッピング開始アドレスを有し、このカーネルキャッシュ領域(システム呼び出しmmap()実装の結果)を共有できるためである.カーネルBufferからユーザーBuffer、Socket Bufferへのコピーは、カーネルBufferからSocket Bufferへの直接コピーになります.