仮想メモリに関する文献のほとんどは、アプリケーション開発者として、仮想メモリを理解することがその強力な機能を活用するのに役立つことを指摘しています。Linux でのアプリケーション開発にしばらく携わっていましたが、コーディング中は複雑な仮想メモリについては気にしませんでした。何か不足していますか?もしそうなら、仮想メモリの仕組みを活用する方法を教えてください。そうでなければ、私が質問に意味をなさないかどうか教えてください!
5 に答える
まあ、コンセプトは実際にはかなり単純です。ここでは繰り返しませんが、OS 設計に関する本を手に取ってください。そこで説明されています。Silberschatz と Galvin の "Operating System Concepts" をお勧めします - これは私が大学で使用しなければならなかったもので、良いものです。
仮想メモリの知識から得られると思われるいくつかのことは次のとおりです。
- 無駄を避けるためにページ境界にメモリを割り当てることを学ぶ (通常のヒープ/スタック メモリではなく、仮想メモリにのみ適用されます);
- 一部のページを RAM にロックして、HDD にスワップされないようにします。
- ガーディアンページ;
- いくつかのアドレス範囲を予約し、後で実際のメモリをコミットします。
- セキュリティを強化するために NX (非実行可能) ビットを使用している可能性がありますが、これについてはよくわかりません。
- 32 ビット システムで >4GB にアクセスするための PAE。
それでも、これらはすべて、非常に特定のシナリオでしか使用できません。実際、アプリケーションの 99% はこれを気にする必要はありません。
追加:とはいえ、こうしたシナリオが発生したときに特定できるように、これらすべてのことを知っておくことは間違いなく良いことです。注意してください - 力には責任が伴います。
ちょっと漠然とした質問です。
仮想メモリを使用できる方法は、主にメモリ マップ ファイルを使用することです。詳細については、mmap() のマニュアル ページを参照してください。
ただし、動的ライブラリはマップされたファイルとして実装されており、多くのデータベース ライブラリもそれらを使用しているため、とにかく暗黙的に使用している可能性があります。
高水準言語からマップされたファイルを使用するためのインターフェースは、多くの場合非常に不便であり、あまり役に立ちません。
マップされたファイルを使用する主な利点は次のとおりです。
- ファイルの一部にアクセスする際のシステム コールのオーバーヘッドがない (ページ フォールトが発生した場合、ページ フォールトはおそらく同じくらいのオーバーヘッドを持つため、これは実際には不利になる可能性があります)
- OS バッファからアプリケーション バッファにデータをコピーする必要はありません - これによりパフォーマンスが向上します
- プロセス間でメモリを共有する機能。
いくつかの欠点は次のとおりです。
- 32 ビット マシンはアドレス空間を簡単に使い果たすことができます
- ファイル拡張を正しく処理するのは難しい
- 現在常駐しているページの数/ページを確認する簡単な方法はありません (ただし、いくつかの方法がある場合があります)
- ページ フォールトによって IO 要求が発生し、スレッドがブロックされる可能性があるため、リアルタイム アプリケーションには適していません (ファイルはメモリ内でロックできますが、十分な容量がある場合に限られます)。
今日のほとんどのアプリケーションでは、プログラマーはコンピュータ メモリの動作を意識しなくても害はありません。しかし、場合によっては (たとえば、プログラムのフットプリントを改善したい場合など)、自分でメモリを操作しなければならなくなることがあります。このような状況では、メモリがどのように機能するように設計されているかを知ることが不可欠です。
言い換えれば、仮想メモリがなくても生きていけるとはいえ、仮想メモリについて学ぶことは、より優れたプログラマになるだけです。
ウィキペディアの記事は良い出発点になると思います。
10 件中 9 件のケースで、仮想メモリ管理について心配する必要はありません。それがカーネルの仕事です。一部の高度に専門化されたアプリケーションでは、それらを微調整する必要がある場合があります。
Linux に重点を置いてコンピューターのメモリ管理について説明している記事を 1 つ知っています [ http://lwn.net/Articles/250967 ]。お役に立てれば。
パフォーマンスに関心がある場合は、メモリ階層を理解することが重要です。
物理メモリに完全に含まれる小さなデータ セットの場合、キャッシュに注意する必要があります (キャッシュからメモリにアクセスする方がはるかに高速です)。
物理メモリ不足のためにページ アウトされる可能性がある大きなデータ セットを扱う場合は、アクセス パターンをローカライズするように注意する必要があります。
たとえば、C で行列を宣言すると ( int a[rows][cols])、行単位で割り当てられます。したがって、マトリックスをスキャンするときは、列ではなく行でスキャンする必要があります。そうしないと、同じデータを何度もページインおよびページアウトすることになります。
もう 1 つの問題は、メモリに保持されているダーティデータとクリーンデータの違いです。クリーン データとは、プログラムによって変更されていないファイルから読み込まれた情報です。OS は、クリーンなデータをディスクに書き込まずにページ アウトする場合があります (おそらく、ロード方法によって異なります)。ダーティ ページは、最初にスワップ ファイルに書き込む必要があります。