メモリー管理とか vmallocとか

少々古い記事: IBM Developer 日本語版 : 大変申し訳ありません。このページは無効です。

大容量メモリーの使用を (今までなかった訳じゃないけど)改善するための変更

  • リバース・マッピング: メモリーマネージャーが スワップアウト対象のページをマップしているプロセス全て, を見つけるのに, 巨大なメモリーを使用してたばーい (traverse作業などで)ボトルネックだったけど, RMAPの実装で ・・・
  • ラージページ: 一部のアプリケーションでは非常に大量のメモリを使ったりして 4KBのページサイズでは問題になったりする。1GB割り当てだと, 256K個の PTEで ひとつ 8Bとすると 2MB, 複数のプロセスでソレを共有したとしてそれぞれに 2MB必要。x86では, 物理アドレス拡張(PAE)がオンになっているシステムなら PAGE_SIZEは 2MBとか 4MB。 「大きなサイズのページを使うと translation lookaside buffer (TLB)の使い残しも減る」らしい。
  • ページテーブル・エントリを高位メモリに保存: 32ビットのマシンでは通常, ページテーブルは低位メモリにしか保存できない, らしい (物理メモリの最初の 896MB内)。Highmem PTEと呼ばれる設定オプションで高位メモリに置ける。けど, 普通そーなってる気がする。以下, 参考: include/linux/mmzone.h
    • 最初の 0x01000000 (16M)までが ZONE_DMA
    • 次の 0x38000000 (896M)までが ZONE_NORMAL
    • ソレ以降は ZONE_HIGHMEMな感じ

ちなみに, ページ拡張モード(Paging Size Extensions; PSE) と 物理アドレス拡張(Physical Address Extention; PAE), たぶんどちらも稼働中には変更できない, とか思うけど。
include/asm-i386/pgtable.hに _PAGE_PSEとか _PAGE_BIT_PSEとかあったりする。つまり領域によってそーゆーページになってたりするのカナ?

http://www.linux.or.jp/JF/JFdocs/The-Linux-Kernel-4.html
IBM Developer 日本語版 : 大変申し訳ありません。このページは無効です。

内容は難しくないかもだけど (作るのは話が別だし), 用語がいろいろ出てきてたりして。

  • メモリマッピング (memory mapping)
  • ページフレーム番号 (Page Frame Number, PFN), 物理ページフレーム番号, 仮想ページフレーム番号
  • ページテーブルエントリ (PTE)
  • アドレス変換バッファ (Translation Look-aside Buffer, TLB)

Linux では 3レベルのページテーブルの存在が前提, らしい。Intel x86(32bit版)では 2レベルのページテーブル。さらに PSEだと, 1レベルっぽい感じ。

  1. Directoryは 10MSB (上位ビット)
    • Page Global Directory, PGD
    • Page Middle Directory, PMD ・・・ x86では, 「何もしない PMD」になってるらしい
  2. Tableは中間の 10ビット ・・・ page table entry, PTE
  3. Offsetは 12LSB (下位ビット) ・・・ PAGE_SIZE=4096だし

拡張ページングだと, Directoryは 10MSB, (Tableは存在せずに) Offsetが 22LSB。んで, 36bitの PSEは 36bitの物理アドレスサポート。
たぶん CONFIG_HIGHMEM4Gが普通のアレで, CONFIG_HIGHMEM64Gが PSEってことカナ。「PAEにより最大 64GBまでアクセス可能」ってことだから, PAEが CONFIG_HIGHMEM64Gのことかもしれない。ただし, PAEを使うことができても 32bit版では 16GBを超える RAMを超える RAMを使用することは勧めらんないらしい。

カーネル・コードとデータ構造専用にいくつかのページ・フレームが予約されている。これらのページがディスクにスワップされることはない。てことで, PAGE_OFFSET (0xC0000000)以降は常駐, 0x00000000〜PAGE_OFFSETまではユーザー・コード (&カーネル・コードからも参照)。つまり 3GBのトコに境界線。
CONFIG_HIGHMEMと関係があるのとばかり思ってたけど, こちらは先の通り 896MBのゾーンで, だから(?) ソレが指定されていないと物理メモリーは 1GB付近までしかダメっぽい。

すべてのプロセス仮想メモリは mm_structデータ構造体で表現される。これには, 現在実行中のイメージの情報と同時に, いくつかの vm_area_structデータ構造体へのポインタも含まれる, らしい。で, その vm_area_structデータ構造体には そのメモリに対する一連の操作ルーチンも含まれている。メソッドのこと? カナ。nopage操作とか swapinの時の処理とか。

σ(^^) なりのまとめ っつーか ・・・

他のアーキテクチャーだけど, ARM Linuxでのそーゆー情報があったり。んで, 基本的には phys = virt - PAGE_OFFSET + PHYS_OFFSET。OS自体ではページテーブル使ったり (アドレス変換)せずに 直接アクセス。
てな訳で, Kernel空間 1GBってことは実メモリーも (本来なら)それが MAXなはず。ただしコレは x86での話で, 多くのアーキテクチャーでは 3GB-1GBの空間分割は行わずに 効率よく 4GB付近までの実メモリーを扱えるのだとか。

vmallocは, 実メモリーが存在しない空間に, こー, メモリーを割り当てる, みたいな。その範囲としては VMALLOC_STARTから VMALLOC_ENDまで (x86では include/asm-i386/pgtable.h)。実メモリーの最後のトコが変数 high_memoryに入ってるので, その少しあとからその領域。
ZONE_HIGHMEMは, だから 1GB - vmalloc予約領域 (128MB)で, 896MBのトコってことなのカモ。
参考:

ただし, 2.6 Kernelでは x86でも 4G/4Gサポートとゆーことなので, んーと ・・・ 何かが異なるのかも。