Linuxにおける直接I/Oメカニズムの紹介


http://www.ibm.com/developerworks/cn/linux/l-cn-directio/
ダイレクトI/Oの動機
直接I/Oを紹介する前に、このセクションでは、従来のI/O操作にどのような欠点があるのか、直接I/Oというメカニズムが現れる理由について説明します.
キャッシュI/O(Buffered I/O)とは
キャッシュI/Oは標準I/Oとも呼ばれ、ほとんどのファイルシステムのデフォルトI/O操作はキャッシュI/Oです.LinuxのキャッシュI/Oメカニズムでは、オペレーティングシステムはI/Oのデータをファイルシステムのページキャッシュ(page cache)にキャッシュします.つまり、オペレーティングシステムカーネルのバッファにデータがコピーされてから、オペレーティングシステムカーネルのバッファからアプリケーションシーケンスのアドレス空間にコピーされます.キャッシュI/Oには、以下のような利点があります.
キャッシュI/Oはオペレーティングシステムのカーネルバッファを使用し、アプリケーション空間と実際の物理デバイスをある程度分離します.
キャッシュI/Oは、リードディスクの回数を減らし、パフォーマンスを向上させることができます.
アプリケーションがデータのブロックを読み取りようとすると、このデータがページキャッシュに格納されている場合、実際の物理ディスク操作を必要とせずに、このデータをすぐにアプリケーションに返すことができます.もちろん、アプリケーションが読み込む前にページキャッシュにデータが格納されていない場合は、ディスクからページキャッシュにデータを読み込む必要があります.書き込み操作については、アプリケーションがページキャッシュにデータを先に書き込むこともあります.データがすぐにディスクに書き込まれるかどうかは、アプリケーションが採用する書き込み操作メカニズムに依存します.ユーザーが同期書き込みメカニズム(synchronous writes)を採用している場合、データはすぐにディスクに書き込まれ、アプリケーションはデータが書き終わるまで待っています.ユーザが遅延書き込みメカニズム(deferred writes)を採用している場合、アプリケーションはデータがすべてディスクに書き込まれるまで待つ必要はありません.データはページキャッシュに書き込まれるだけでいいです.遅延書き込みメカニズムの場合、オペレーティングシステムは定期的にページキャッシュに格納されたデータをディスクにブラシします.非同期書き込みメカニズム(asynchronous writes)とは異なり、遅延書き込みメカニズムは、データがディスクに完全に書き込まれたときにアプリケーションに通知されず、非同期書き込みメカニズムは、データがディスクに完全に書き込まれたときにアプリケーションに返されます.したがって,遅延書き込みメカニズム自体はデータ損失のリスクがあり,非同期書き込みメカニズムではこのような心配はない.
キャッシュI/Oの欠点
キャッシュI/Oメカニズムでは、DMA方式は、データを直接ディスクからページキャッシュに読み返すか、ページキャッシュから直接ディスクに書き込み、アプリケーションのアドレス空間とディスクとの間でデータ転送を行うことができないため、転送中にアプリケーションのアドレス空間とページキャッシュとの間でデータコピー操作を複数回行う必要がある、これらのデータコピー操作によるCPUおよびメモリのオーバーヘッドは非常に大きい.
特定のアプリケーションでは、オペレーティング・システムのカーネル・バッファを避けてアプリケーション・アドレス・スペースとディスク間でデータを直接転送することは、オペレーティング・システムのカーネル・バッファを使用するよりもパフォーマンスが向上します.次のセクションで説明するセルフ・キャッシュ・アプリケーションの1つです.
セルフキャッシュアプリケーション(self-cachingアプリケーション)
一部のアプリケーションでは、オペレーティングシステムカーネルのキャッシュメモリを使用する必要がなく、セルフキャッシュアプリケーション(self-caching applications)と呼ばれる独自のデータキャッシュメカニズムがあります.データベース管理システムは、このようなアプリケーションの代表です.セルフキャッシュアプリケーションは、物理的な表現ではなく、データの論理的な表現を使用する傾向があります.システムメモリが低い場合、セルフキャッシュアプリケーションは、ディスク上の実際のデータではなく、このデータの論理キャッシュをスワップします.セルフキャッシュ・アプリケーションは、操作するデータの意味をよく知っているので、より効率的なキャッシュ置換アルゴリズムを採用することができます.セルフキャッシュ・アプリケーションが複数のホスト間でメモリを共有する可能性がある場合、セルフキャッシュ・アプリケーションは、ユーザー・アドレス空間のキャッシュ・データを効率的に無効にするメカニズムを提供し、アプリケーション・アドレス空間のキャッシュ・データの一貫性を確保する必要がある.
キャッシュI/Oは、キャッシュ・アプリケーションにとって明らかに良い選択ではありません.ここでは,Linuxにおける直接I/O技術を重要に紹介している.Linuxの直接I/O技術は、キャッシュI/O技術におけるオペレーティングシステムのカーネルバッファの使用を省略し、データをアプリケーションのアドレス空間とディスクとの間で直接転送することで、複雑なシステムレベルのキャッシュ構造を省略することができ、一方、プログラムが独自に定義したデータ読み書き管理を実行することで、システムレベルの管理がアプリケーションのデータへのアクセスに与える影響を低減します.次のセクションでは、Linuxで提供される直接I/Oメカニズムの設計と実装に重点を置きます.このメカニズムは、セルフキャッシュアプリケーションに良いサポートを提供します.
Linux 2.6における直接I/O技術
Linux 2.6で提供されるいくつかのファイルアクセス方法
すべてのI/O操作は、ファイルの読み取りまたは書き込みによって行われます.ここでは、キーボードやディスプレイを含むすべての周辺機器を、ファイルシステム内のファイルと見なしています.ファイルへのアクセス方法は様々ですが、Linux 2.6でサポートされているいくつかのファイルへのアクセス方法を以下に示します.
識別子名
識別子の説明O_RDONLY
読み取り専用でファイルを開くO_WRONLY
ファイルを書き込みのみで開くO_RDWR
ファイルを読み書きで開くO_CREAT
ファイルが存在しない場合は、ファイルを作成します.O_EXCL
ファイルを独占モードで開く.O_を同時に設定するとEXCLとO_CREATE、ファイルが既に存在する場合、開く操作は失敗しますO_NOCTTY
この記述子を設定すると、そのファイルは端末として処理されてはならないO_TRUNC
ファイルを切断し、ファイルが存在する場合は削除します.O_APPEND
記述子を設定すると、ファイルを書く前にファイルポインタがファイルの下部に設定されます.O_NONBLOCK
ブロックなしでファイルを開くO_NELAY
同O_NELAY、O_を同時に設定するとNELAYとO_NONBLOCK,O_NONBLOCKが優先的に機能するO_SYNC
この記述子は通常のファイルの書き込みに影響します.この記述子を設定すると、データがディスクに書き込まれるまでファイルの書き込みは終了しません.FASYNC
この記述子を設定すると、I/Oイベント通知は信号によって発行されるO_DIRECT
この記述子は直接I/Oのサポートを提供するO_LARGEFILE
この記述子は2 GBを超える大ファイルのサポートを提供するO_DIRECTORY
この記述子は、開いているファイルがディレクトリでなければならないことを示します.そうしないと、開く操作に失敗します.O_NOFOLLOW
この記述子を設定すると、パス名の末尾のシンボルリンクは解析されません.
ダイレクトI/O技術の特徴
ダイレクトI/Oのメリット
直接I/Oの最も主要な利点は、オペレーティングシステムのカーネルバッファとアプリケーションのアドレス空間のデータコピー回数を減らすことで、ファイルの読み取りと書き込みに伴うCPUの使用やメモリ帯域幅の消費を低減することです.これは、セルフキャッシュアプリケーションなどの特定のアプリケーションにとって良い選択です.転送するデータ量が大きい場合は、オペレーティングシステムのカーネルアドレス空間コピーデータ操作の参加を必要とせずに、直接I/O方式でデータ転送を行い、パフォーマンスを大幅に向上させることができます.
直接I/Oの潜在的な問題
直接I/Oは必ずしも満足できる性能の飛躍をもたらすとは限らない.ダイレクトI/Oを設定するコストは非常に大きく、ダイレクトI/OはキャッシュI/Oのメリットを提供しません.キャッシュI/Oの読み取り操作はキャッシュメモリからデータを取得することができ、直接I/Oの読み取り操作はディスクの同期読み取りをもたらし、これは性能の違いをもたらし、プロセスが実行するのに長い時間がかかる.書き込みデータ操作では、直接I/Oを使用するにはwrite()システム呼び出し同期実行が必要です.そうしないと、アプリケーションはいつI/Oバッファを再使用できるか分かりません.ダイレクトI/O読み取り操作と同様に、ダイレクトI/O書き込み操作によってアプリケーションのシャットダウンが遅くなります.したがって,アプリケーションが直接I/Oを用いてデータ転送を行う場合,通常は非同期I/Oと組み合わせて使用される.
まとめ
LinuxでのダイレクトI/Oアクセスファイル方式では、CPUの使用率やメモリ帯域幅を削減できますが、ダイレクトI/Oはパフォーマンスに悪影響を及ぼす場合があります.したがって、直接I/Oを使用する前に、バッファI/Oを設定するコストが非常に大きいと判断した場合にのみ、直接I/Oを使用することを考慮する必要があります.直接I/Oは常に非同期I/Oと組み合わせて使用する必要がありますが、本稿では非同期I/Oについて詳しく説明していません.興味のある読者はLinux 2.6に関するドキュメントを参照してください.