メモリー管理とか 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レベルっぽい感じ。
Directory
は 10MSB (上位ビット)- Page Global Directory, PGD
- Page Middle Directory, PMD ・・・ x86では, 「何もしない PMD」になってるらしい
Table
は中間の 10ビット ・・・ page table entry, PTEOffset
は 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サポートとゆーことなので, んーと ・・・ 何かが異なるのかも。