web-dev-qa-db-ja.com

メモリマップページと匿名ページとは何ですか?

Linuxでメモリマップページと匿名ページを理解できません。誰かが例でそれを説明できますか?それらに関連するカーネルデータ構造は何ですか?

27
bornfree

正しい用語は、メモリマップファイルおよび匿名マッピングです。メモリマッピングを参照する場合、通常はmmap(2)を参照します。 mmapの使用には2つのカテゴリがあります。 1つのカテゴリは、共有マッピングとプライベートマッピングです。もう1つのカテゴリは、FILEとANONYMOUSのマッピングです。混合すると、次の4つの組み合わせが得られます。

  1. プライベートファイルマッピング
  2. 共有ファイルのマッピング
  3. プライベートな匿名マッピング
  4. 共有匿名マッピング

ファイルマッピングは、メモリ上にNバイトがマッピングされるディスク上のファイルを指定します。関数mmap(2)は、4番目の引数として、メモリにマップされるファイルへのファイル記述子を受け取ります。 5番目の引数は、オフセットとして読み込まれるバイト数です。 mmapを使用してメモリマップファイルを作成する一般的なプロセスは、

  1. ファイル記述子を取得するためのopen(2)ファイル。
  2. fstat(2)ファイル記述子データ構造からサイズを取得するファイル。
  3. mmap(2)open(2)から返されたファイル記述子を使用するファイル。
  4. close(2)ファイル記述子。
  5. メモリマップファイルに対して何でも行います。

ファイルがPRIVATEとしてマップされている場合、加えられた変更は基になるファイルにコミットされません。これは、ファイルのプライベートなメモリ内コピーです。ファイルがSHAREDにマップされると、行われた変更はカーネルによって自動的に基礎となるファイルにコミットされます。共有としてマップされたファイルは、いわゆるメモリマップI/OおよびIPCに使用できます。ファイルの永続性が必要な場合は、共有メモリセグメントの代わりにIPCにメモリマップファイルを使用します

プロセスの初期化を監視するためにstrace(1)を使用すると、ファイルのさまざまなセクションがプライベートファイルマッピングとしてmmap(2)を使用してマップされていることがわかります。同じことがシステムライブラリにも当てはまります。

ライブラリーをプロセスにマップするためにmmap(2)が使用されているstrace(1)からの出力の例。

open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=42238, ...}) = 0
mmap(NULL, 42238, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff7ca71e000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\341n8\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0
mmap(0x386ee00000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x386ee00000

匿名のマッピングはファイルによってサポートされていません。具体的には、MAP_ANONYMOUSフラグがmmap(2)の3番目の引数として使用されている場合、mmap(2)の4番目(ファイル記述子)および5番目(オフセット)の引数は使用されません。 MAP_ANONYMOUSフラグを使用する代わりに、/ dev/zeroをファイルとして使用することもできます。

「匿名」という言葉は、ファイルが匿名でマッピングされているかのように聞こえるという点で、私にとっては不適切な選択です。代わりに、匿名のファイルです。ファイルが指定されていません。

ユーザーの土地プログラミングでは、プライベートな匿名マッピングの使用はほとんどありません。共有匿名マッピングを使用して、アプリケーションがメモリの領域を共有できるようにすることもできますが、代わりにSYSVまたはPOSIX共有メモリを使用しない理由はわかりません。

匿名マッピングを使用してマップされたメモリはゼロで埋められることが保証されているため、メモリのゼロで埋められた領域がこの方法でmalloc(2)+ memset(2 )コンボ。

52
typedeaf

私が理解しているように、マップされたページは具象ファイルのマッピングであるのに対し、匿名のページには名前が付けられたファイルシステムソースがないため、名前が付けられています。たとえば、任意のユーザースペースプロセスで単純なmalloc操作を使用してanonymosページを取得できます...

カーネル構造について:明らかにstruct pageですが、匿名のページの場合はstruct anon_vmaがページに配置されます->マッピング、およびマップされたページの場合- struct address_space、具体的なiノードに接続されています。

8
Alex Hoppus

メモリマップページの意味がわかりません。だから私はそれについて話すつもりはありません。

匿名ページについては、通常、カーネルがページフレームの再利用を行うときに参照されます。匿名ページのインスタンスには、プロセスのスタック、ヒープ、共有メモリ、および変更された共有ライブラリが含まれます。 Linuxでは、すべての動的共有ライブラリは、次のようなシステムコールを通じてプロセスの仮想メモリアドレス空間にマップされます。

firo@linux-6qg8:~> strace -e mmap,openat ls 2>&1 |grep -A1 libc.so
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
mmap(NULL, 3906144, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0)

MAP_PRIVATEedファイル/ライブラリに属する​​ページへの書き込みは、ファイルバックエンドページから匿名ページへの変更をトリガーします。

定義上、匿名ページは匿名メモリとも呼ばれ、カーネルがページフレームを再利用するときにスワップ先のバックエンドデバイスを持たない一種のページです。これがLinuxがスワップ領域をサポートする理由です。

匿名ページに関連するカーネルデータ構造には2種類あります。

  1. 匿名ページを取り戻すために、カーネルはPTE(ページテーブルエントリ)を変更するために匿名ページを使用しているすべてのプロセスを知る必要があります。これをリバースマッピングまたはrmapと呼びます。

    struct address_spaceは、逆マッピングを維持するために共有メモリによって使用されます。

    struct anon_vmaは、リバースマッピングを維持するために残りの匿名ページで使用されます。

  2. カーネルはLRUアルゴリズムを使用してページフレームを再生します。カーネル5.0以降の場合、struct pglist_dataのstruct lruvecを確認してください

2
firo