Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
ページフレーム管理
吉田雅徳
2014/6/28(Sat)
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
ページフレームの管理
• 目的
• 物理メモリをページフレーム(4KB)の集まりと
して管理(割当・解放)
• 異なる種類のメモリを効率的に利用(NUMAノー
ド、メモリゾーン、percpu、など)
2
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
アジェンダ
• 1. ページフレーム
• 2. NUMA
• 3. メモリゾーン
• 4. ページフレーム割当
• 4.1 ゾーンアロケータ
• 4.2 バディシステム
• 5. ページフレーム解放
3
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
1. ページフレーム
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
x86ページング超概要(1)
• Mode
• Real-address mode
• 16bit addressing
• Segmentationによるアドレス変換(Logical→Linear)は常に有効
• Linear address = Physical address
• Protected mode
• 32bit addressing
• Segmentationにおいて保護機構が有効になっている状態を指す
• Pagingのon/offは直交する要素(どちらもアリ)
• IA-32e mode
• Enabled by IA32_EFER msr s bit8
• 2 sub modes: Compatibility mode(32bit) and 64-bit mode
5
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
x86ページング超概要(2)
• Address
• Logical address
• カーネルを含むプログラムが直接扱うアドレス(セグメントセレクタ+オフセットからなる(但し普通のプロ
グラムではデフォルトのセグメントセクレタのみを使うので、省略され、あまり意識されない。TLSとか
per-cpuとかで%%gfを指定したりはする))
• Segmentationが適用され、Linear addressに変換される
• Linear address
• Pagingがdisabledであれば、Physicalアドレスと同一のものとして扱われる
• Pagingがenabledであれば、Pagingが適用され、Physical addressに変換される
• Physical address
• メモリアドレスバスに対して指定するアドレス
• 必ずしもRAM上の位置に対応するオフセットではない(最終的に当該アドレスが何のデバイスの何の値にマッ
ピングされるかはHW環境次第)
6
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
x86ページング超概要(3)
• 以降は、IA-32e mode(64-bit sub mode)を前提として説明を進める。
• Pagingとは
• メモリ上に構築されたpage table structureをMMU(Memory Management Unit)
が解釈し、Linear→Physicalのアドレス変換、保護制御、キャッシュ制御を実行。
• 上記MMU処理の単位である4KBをページと呼ぶ。但しpage tableの指定により
2MB、1GBを1ページとして扱うことも可能。
• ページフレームとは(赤本の定義に準拠)
• 特にRAMについて、領域をページサイズ・ページアラインで区切った時の、各ブ
ロックを「ページフレーム」と呼ぶ。
• すなわち、カーネルが所謂メモリを有限リソースとして管理する際の最低単位。
7
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
struct page
• ページフレームに一対一で用意され、種々の情報を格納
• ページディスクリプタとも(赤本などでは)呼ばれる
• (有名な話だが)1個のサイズは、キャッシュライン(i7なら64B)
に収まるよう保たれており、サイズ拡張は原則論外とされる
• (あまり知られてないと思うが)中身は更にdouble word(64bit
環境なら16バイト)x4にアラインするように作られている。

これは、slubのコードでcmpxchg_doubleとかいう atomic
操作を行うため(らしい)
8
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
mem_map
• 全RAMページフレームに対応するstruct pageを一
つの配列に格納したもの。
• 牧歌的な実装・・・

#define __pfn_to_page(pfn) ¥

(mem_map + ((pfn) - ARCH_PFN_OFFSET))
• ところが、CONFIG_NUMA+CONFIG_X86_64(と
いうかCONFIG_SPARSEMEM)では、全メモリ統
一のmem_mapは存在しない。
9
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
sparse memoryでの
__pfn_to_page()
• #define __pfn_to_page(pfn) 

({ unsigned long __pfn = (pfn); 

struct mem_section *__sec = __pfn_to_section(__pfn); 

__section_mem_map_addr(__sec) + __pfn; 

})
• 二段テーブル構造
• 1段目:struct mem_sectionのリスト
• 2段目 : mem_section::section_mem_map

ある長さの連続領域(後述するように128MB分)の中のページフレーム
に対応するミニmem_mapの役割
• sparseな物理メモリレイアウトに対応。
10
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
RAM情報の取得
• __init memblock_x86_fill()
• 物理メモリ上の何処がRAMにマップされている
か特定する関数
• BIOS(e820)から得たRAM領域情報を使い、

memblockリストを作成。

(E820_RAMまたはE820_RESERVED_KERNな
e820entry毎に、memblock_add()を呼び出し)
11
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
mem_section(離散型mem_map)の

作成
• void __init sparse_memory_present_with_active_regions(int nid)

{

unsigned long start_pfn, end_pfn;

int i, this_nid;



for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, &this_nid)

memory_present(this_nid, start_pfn, end_pfn);

}
• for_each_…は前頁で作成したmemblockリストをiterationする
もの。memory_present()の中では、memblockを128MB長毎に
区切り、それぞれmem_sectionを作成する。
• 128MB = PAGE_SIZE * (2MB / sizeof(struct page))。

つまり、一つのmem_sectionが保持するミニmem_mapのサイズ
がhuge pageに収まるようにしている。
12
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
2. NUMA
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
NUMAって
• NUMA(Non-Uniform Memory Architecture)
• CPUからメモリの距離(レイテンシ)が一様でない
• 各CPUと各メモリの全対全に特性が定義される?
• => No.

1個以上のCPU群と最大1個の物理メモリレンジからなる
nodeを単位として、node間(or同node内)で特性が定義
される。
• x86ではACPIから構成情報を取得する。
14
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
ACPIからNUMA情報取得
• __init initmem_init()

-> __init x86_numa_init()

-> __init numa_init(init_func=x86_acpi_numa_init)
• ACPIからNUMA情報を取得
• SRAT(Static Resource Affinity Table)
• SLIT(System Locality Information Table)
• 最終的にstruct pglist_data(pg_data_t)をセット
アップ
15
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
ACPI SRAT
• pxm_to_node_map[MAX_PXM_DOMAINS]

node_to_pxm_map[MAX_NUMNODES]
• nodeとACPI proximity domainの双方向マッピング
• LinuxではACPI proximity domainをnodeに抽象化

(可搬性:ACPI以外でNUMAサポートしてるアーキがある(多分))
• __apicid_to_node[MAX_LOCAL_APIC]
• APIC ID(=x86アーキ内部でのCPU番号)からnodeへの単方向マッピング
• numa_meminfo
• 物理メモリ範囲(start+end)とnodeの双方向マッピング

(この範囲に稠密にRAMがマップされてるとは限らないのでe820情報も使う)
16
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
ACPI SLIT
• SLIT(System Locality Information Table)
• node(proximity domain)間の距離の情報
• 1byte(0 255)で定義される。
• 0 9=予約済、255=node間アクセス不可
• 10 29: 比較的近い(zone_reclaim対象(後述))
17
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
NODE情報の保存
• __init numa_register_memblks()
• ACPI SRAT/SLITから得た情報に基づき、
node_data[]を設定
• node_data[]はNUMA_NODE(nid)マクロ経由で
使用される、NUMA情報を格納する構造体
18
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
CPUとNODEのマッピング
• 先ほど、ACPIから得た情報
• __apicid_to_node[MAX_LOCAL_APIC]
• APIC IDからnodeへの単方向マッピング
• だがしかし:Linuxにおけるprocessor ID != ACPI ID
• processor IDとAPIC IDのマッピング
• early_per_cpr(x86_cpu_to_apicid)に格納(別途、APIC周りの初期化処理による)
• 上記2種のテーブルをマージして、最終的に
• per_cpu(node_map, cpu)を設定する。cpu_to_node()ユーティリティ関数で参照
• processor IDからnode IDへのマッピング。
19
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
3. メモリゾーン
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zoneとは
• zoneとは、物理メモリをアドレスによって分類したもの。
• enum zone_type {

ZONE_DMA, //<16MB

ZONE_DMA32, //<4GB

ZONE_NORMAL, //全部

ZONE_HIGHMEM, //x86_64では定義しない

ZONE_MOVABLE, //???

__MAX_NR_ZONES

};
• ZONE_MOVABLEって?
• migrationによるページ移動を許可する領域。デフォルトでは存在しない。カーネルオプショ
ン kernelcore= で設定(ZONE_NORMALのサイズを設定する。但し=0の場合は
ZONE_MOVABLEは作られない)
• __GFP_MOVABLEを指定した時のみ、当該ゾーンからページを割当てる。
• Memory hot-removeに必須(movableなメモリのみremove可能)。
21
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
NUMAノード毎のzone/zonelist
• typedef struct pglist_data {

struct zone node_zones[MAX_NR_ZONES];

struct zonelist node_zonelists[MAX_ZONELISTS];

int nr_zones;

…

};
• node_zones[]
• node配下のzoneのリスト。どのnodeも全てのゾーンを持つ。

(但し、幾つかの又は全てのnodeが空の場合もある)
• node_zonelists[]
• nodeに属すCPUがメモリ割当を実行する際に、

割当を試行する対象となるzoneを、試行する順序で並べたもの。
22
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
struct zonelist node_zonelists[]
• サイズはCONFIG_NUMAなら2、さもなくば1
• node_zonelists[0]
• 実行中CPUが属すNODEから割当可能な全てのzone(任
意のzone)を含むリスト
• node_zonelists[1]
• 実行中CPUが属すNODE内のzoneのみを列挙したリ
スト(__GFP_THISNODEで使用)
23
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zonelists[0]の順序
• zonelists[0]内のzoneの順序はsysctlで変更可能。
• zone
• Higher zoneから優先して使う方法。ローカルのZONE_DMA32よりもリモート
のZONE_NORMALを先に使う。DMA領域温存を優先するポリシー。
• node
• 近傍NUMA nodeから優先して使う方法。局所性を優先するポリシー。
• default
• ZONE_DMAとZONE_NORMALのサイズを比較し、 zone か node かを自動的
に選択(ZONE_NORMALの割合が十分大きければDMA領域温存を重視し
て zone 、小さければ node )
24
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::watermark[NR_WMARK]
• ページ割当時に、フリーページ量に応じて動作変更を行う。3種類ある(min <
low < high)。
• WMARK_LOW

zonelistの全zoneでフリーページ量がlowを下回ってると、slowpathへ移行。

この段階で、kswapdを起床するが、そのページ回収完了は待たずにページ割
当を実行(非同期的ページ回収)
• WMARK_MIN

minも下回っていると、slowpathの延長で自らページ回収(同期的ページ回収)
• WMARK_HIGH

node毎に動作するkswapdは一度起床されると、配下の全zoneのフリーペー
ジがhighを超えるまで動作し続ける。
25
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::lowmem_reserve[MAX_NR_ZONES]
• どのzoneからメモリ割当の試行を開始するかは、GFPフラグで
決まる(大抵はZONE_NORMAL)から。
• 高位zone(e.g. _NORMAL)でのページ割当に失敗して、低位
zone(e.g. _DMA32)でページ割当を試行する際に、watermark
に一定量(=reserve)を加算して割当のハードルを上げる。
• z0から割当試行を開始して、z1にfall backしてきた場合、z1-
>lowmem_reserve[z0]がreserveになる。
• 同じzone_type(e.g. _NORMAL同士)ではreserveは0。
26
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone_watermark_ok()
(watermark判定ロジック)
• 目的:引数で指定したwatermark値とフリーページ量を比較して、割当可否を判定
• 主要な引数:order(割り当てたいページのオーダ数)、mark(判定に使うwatermark値)、alloc_flags(GFP由来のフラグ)
• 処理
1. alloc_flagsに基づきmarkを調整
• ALLOC_HIGH => markを1/2
• ALLOC_HARDER => markを1/4
2. orderサイズのページ割当後のフリーページ総数が、mark+lowmem_reserveを超えているかチェック
3. 更に以下の条件をチェック(フラグメンテーション度合いのチェック)
• オーダが1 MAX_ORDER-1のフリーページ総数がmark>>1を超えているか?
• オーダが2 MAX_ORDER-1のフリーページ総数がmark>>2を超えているか?
• ・・・
• オーダがorder∼MAX_ORDER-1のフリーページ総数がmark>>orderを超えているか?
27
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::dirty_balance_reserve
• 当該zoneにおいて、dirtyにしないメモリ量。

全ページから本reserve値を引いた数が、

dirtyに出来るページ量の限界値となる。
• max(lowmem_reserve) + high_wmark_pagesで算出
/*
* Lowmem reserves are not available to
* GFP_HIGHUSER page cache allocations and
* kswapd tries to balance zones to their high
* watermark. As a result, neither should be
* regarded as dirtyable memory, to prevent a
* situation where reclaim has to clean pages
* in order to balance the zones.
*/
28
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::percpu_drift_mark
• マイナーな機能。zone_watermark_ok_safe()でのみ使われる。
• zone_page_state(z, NR_FREE_PAGES)がpercpu_drift_mark
を下回っていた場合、

zone_page_state_snapshot(percpuのNR_FREE_PAGESも加
算する)をfree_pagesとして、__zone_watermark_ok()を呼び
出す。
• percpu_drift_mark==0の時は無効
• page 迫時にpercpuのfree pageも動員する、その閾値を決め
るものと見なせる。
29
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::pageset
• 型
• struct per_cpu_pageset __percpu *pageset;
• 各zoneはpercpuのキャッシュを持ち、出来るだけこの
キャッシュからページ割当を行う。

解放時も最初はこのキャッシュへページを追加。
• ページが余ってくるとバディシステムに戻される。
• CPUキャッシュヒット率を高めることが目的。
30
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::free_area[MAX_ORDER]
• zone毎のバディシステム(後述)。
31
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::lruvec
• zone毎の、ユーザページ(無名メモリorページキャッシュ)の使用頻度順に並べた
LRU(Least Recently Used)リスト。ページ回収で使う。
• enum lru_list {

" LRU_INACTIVE_ANON = LRU_BASE,

" LRU_ACTIVE_ANON = LRU_BASE + LRU_ACTIVE,

" LRU_INACTIVE_FILE = LRU_BASE + LRU_FILE,

" LRU_ACTIVE_FILE = LRU_BASE + LRU_FILE + LRU_ACTIVE,

" LRU_UNEVICTABLE,

" NR_LRU_LISTS

};

struct lruvec {

struct list_head lists[NR_LRU_LISTS];

struct zone_reclaim_stat reclaim_stat;

};"
• anon/file及びactive/inactiveを個別に管理している。また、ページ回収対象外の
(mlockされてるページなど)を走査対象から外すための独立したリストとして
unevictableリストも管理される。
32
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone::***_pages
• spanned_pages
• 単にzone_end_pfn - zone_start_pfn。

holesもreserved pagesも含む。
• present_pages
• spanned_pagesからholesを除いたもの。

reserved pagesは含む
• managed_pages
• presend_pagesからreserved_pagesも除いたもの。
• ページ資源管理の文脈では普通、これをzoneの総ページとして扱うことになる。
33
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
4. ページフレーム割当
4.1 ゾーンアローケータ
4.2 バディアロケータ
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
4.1 ゾーンアロケータ
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
alloc_pages
• alloc_pages()

-> alloc_pages_current()

-> get_task_mempolicy()

-> if MPOL_INTERLEAVE:

-> alloc_pages_interleave

(MPOL_INTERLEAVEポリシーでゾーン選択して割当)

-> else:

-> __alloc_pages_nodemask()

-> 初回get_page_from_freelist()

-> for_each_zone_zonelist_nodemaskループ

-> 初回はzonelistの中でローカルnode内のzoneから割当を試行

-> もしダメなら、二回目get_page_from_freelist()

-> for_each_zone_zonelist_nodemaskループ

-> 二回目はzonelistの中のzoneから割当を試行

-> もしダメなら、__alloc_pages_slowpath()
36
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
for_each_zone_zonelist_n
odemaskループ!
1. zone_dirty_limitを越えてない?
• zone内のdirty page cacheの量に閾値がある。溜めすぎるとflush時にシステム止まるため。
2. zone->watermark(ここではlow)を下回ってない?
• sysctl -w zone_reclaim_mode=1 した場合のみ、zone_reclaim()を実行。

でなければこの時点でこのzoneからの割当は諦め
• zone_reclaim():

* Zone reclaim reclaims unmapped file backed pages and

* slab pages if we are over the defined limits.

*

* A small portion of unmapped file backed pages is needed for

* file I/O otherwise pages read by file I/O will be immediately

* thrown out if the zone is overallocated. So we do not reclaim

* if less than a specified percentage of the zone is used by

* unmapped file backed pages.
3. OKなら、このzoneのバディアロケータへ進む
37
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
__alloc_page_slowpath
• 簡単に・・・
1. wake_all_kswapds()
2. if alloc_flags & ALLOC_NO_WATERMARKS:

__alloc_pages_high_priority() … 緊急用メモリを使ってページを割当
3. __alloc_pages_direct_compact()

CONFIG_COMPACTION is unsetなら何もしない
4. __alloc_pages_direct_reclaim()

slow pathの主役っぽい。

try_to_free_pages()してからget_page_from_freelist()を試行
5. __alloc_pages_may_oom()

reclaimのprogressが全く無くなった場合に実行する
6. __alloc_pages_direct_compact()

前回は非同期で、今回は同期的に実行(完了を待つ)
38
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
Memory policy
• Memory policyは、modeとnodemaskで定義される
• mode : MPOL_*** (後述)
• nodemask : mode毎に意味が違うが、基本的には割当に(優
先的に)使われるNUMA node群を示すbit mask
• 関連システムコール
• set_mempolicy(2): set memory policy for a process
• mbind(2): set memory policy for a memory range
39
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
Memory policy mode
• MPOL_PREFERRED
• nodemaskには1つのnodeだけ指定可能。ページ割当時は当該nodeか
らのアロケーションを試行し、失敗時は近傍のnodeへfallback。
• MPOL_INTERLEAVE
• nodemaskに1つ以上のnodeを指定。ページ割当のたびに、初回にアロ
ケーションを試行するnodeをround-robin。
• MPOL_BIND
• nodemaskに1つ以上のnodeを指定。ページ割当のたびに、node番号
昇順にページ割当を試行。nodemask外のnodeに対しては試行しない。
40
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
dirty page flush
• c.f. sysctl/vm.txt
• 3 triggers
• dirty_background_{bytes,ratio}

dirtyメモリがこのバイト数/割合を超えると、background kernel threadがwrite
back開始
• dirty_{bytes,ratio}

ユーザプロセスのwriteによってこの閾値を超えると、プロセスコンテキストの延長
でwrite back開始
• dirty_expire_centisecs, dirty_writeback_centisecs

expire_centisecsを経過すると、ページはoldと見なされる。

oldなページは次回のperiodical write back(周期:writeback_centisecs)でwrite
backされる。
41
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
zone reclaim
• c.f. mm/vmscan.c:3686
• /*

* Zone reclaim reclaims unmapped file backed pages and

* slab pages if we are over the defined limits.

*

* A small portion of unmapped file backed pages is needed for

* file I/O otherwise pages read by file I/O will be immediately

* thrown out if the zone is overallocated. So we do not reclaim

* if less than a specified percentage of the zone is used by

* unmapped file backed pages.

*/
• 目的は恐らく・・・
• zonelistを走査してフリーメモリを探し、全滅だと__alloc_pages_slowpathに入るわけ
だけど、その前にlocal zoneで回収可能なページの回収を試みる。局所性維持が狙い。
42
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
try_to_free_pages,
kswapd, compaction
• ページ回収系については次回以降でお願いします
43
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
4.2 バディアロケータ
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
バディシステム(1)
• 赤本既読を前提に一言で済ませると、フリーページ
のリストを、order毎に分けて管理するもの。

(orderとはページフレームが幾つ物理的に連続して
いるかを2の冪で示したもの。order=nなら2^n個
のページが連続)
• higher orderのページはなるべく割り当てないよ
うにして、fragmentationを防ぐ。
45
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
バディシステム(2)
• 調べきれてないので簡単にポイントだけ
• バディシステムはstruct zone毎に独立して管理される。

nodeまたぎやzoneまたぎの連続ページ割当というのはあり得ないということ。
• freelistは、各order 各migrate_typeに作られる。

migrate_typeはpage migrationとかCMA(continuous memory allocation)に使わ
れる種別値。まだ理解できてない・・・
• order=0の場合のみ、per-cpu cacheがある。

order=0でのアロケーションが失敗すると、per-cpu cacheを充填した上でページを
割り当てる。
• ページは用途に応じてhot or coldがある。これはキャッシュに乗っている可能性が高
い/低いことを示すタームで、割当・解放時に、lruの先頭から/へ割当/解放するか、lru
の末尾にするかを切り分けることができる。デフォルトでは割当/解放ともhot扱い。
46
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
バディアロケータ
• get_page_from_freelist()の最後に実行される
buffered_rmqueue()が本体
• バディシステムからメモリを取ってくる
• 注:watermarkやdirtylimitをクリアしてから実行
されるわけだが、ロックは取ってるわけではないの
で、結局タイミングによっては失敗する可能性あり
47
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
buffered_rmqueue()
• struct page *buffered_rmqueue(…)

{

bool cold = ((gfp_flags & __GFP_COLD) != 0);

again:

if (likely(order == 0)) {

" " pcp = &this_cpu_ptr(zone->pageset)->pcp; /* CPU毎 */

" " list = &pcp->lists[migratetype]; /* migrate type毎 */

" " if (list_empty(list)) {

" " " /* rmqueue_bulk()でバディシステムから補充 */

" " }

" " if (cold) /* hot or cold */

" " " page = list_entry(list->prev, struct page, lru);

" " else

" " " page = list_entry(list->next, struct page, lru);

} else {

" " page = __rmqueue(); /* バディシステムから直接取得 */

" }

" if (prep_new_page(page, order, gfp_flags))

" " goto again;

" return page;

}
48
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
5. ページフレーム解放
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
order=0なページ解放
• free_hot_cold_page(struct page *page , bool cold)
• per-cpuのキャッシュ(zone::pageset)を取り出し、
• hotページは同キャッシュのLRUリストの先頭に、

coldページは同キャッシュのLRUリストの末尾に追加
• per-cpuキャッシュのフリーページが閾値を超えた場
合は、バディシステムへページを返す。
50
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
order>0なページ解放
• free_one_page()
• バディシステムへ指定されたorder分のページを
返す
• 同orderリスト内で連続ページが作成出来たら、
連結して、zone->free_area[order]から

zone->free_area[order+1]へ移動
51
Copyright© 2014 Hitachi, Ltd. All rights reserved. Yokohama Research Lab.
99. 今後
1. ページ回収
2. プロセス空間
3. スラブ(slub, slab, slob)
52

Page frame management

  • 1.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. ページフレーム管理 吉田雅徳 2014/6/28(Sat)
  • 2.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. ページフレームの管理 • 目的 • 物理メモリをページフレーム(4KB)の集まりと して管理(割当・解放) • 異なる種類のメモリを効率的に利用(NUMAノー ド、メモリゾーン、percpu、など) 2
  • 3.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. アジェンダ • 1. ページフレーム • 2. NUMA • 3. メモリゾーン • 4. ページフレーム割当 • 4.1 ゾーンアロケータ • 4.2 バディシステム • 5. ページフレーム解放 3
  • 4.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 1. ページフレーム
  • 5.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. x86ページング超概要(1) • Mode • Real-address mode • 16bit addressing • Segmentationによるアドレス変換(Logical→Linear)は常に有効 • Linear address = Physical address • Protected mode • 32bit addressing • Segmentationにおいて保護機構が有効になっている状態を指す • Pagingのon/offは直交する要素(どちらもアリ) • IA-32e mode • Enabled by IA32_EFER msr s bit8 • 2 sub modes: Compatibility mode(32bit) and 64-bit mode 5
  • 6.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. x86ページング超概要(2) • Address • Logical address • カーネルを含むプログラムが直接扱うアドレス(セグメントセレクタ+オフセットからなる(但し普通のプロ グラムではデフォルトのセグメントセクレタのみを使うので、省略され、あまり意識されない。TLSとか per-cpuとかで%%gfを指定したりはする)) • Segmentationが適用され、Linear addressに変換される • Linear address • Pagingがdisabledであれば、Physicalアドレスと同一のものとして扱われる • Pagingがenabledであれば、Pagingが適用され、Physical addressに変換される • Physical address • メモリアドレスバスに対して指定するアドレス • 必ずしもRAM上の位置に対応するオフセットではない(最終的に当該アドレスが何のデバイスの何の値にマッ ピングされるかはHW環境次第) 6
  • 7.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. x86ページング超概要(3) • 以降は、IA-32e mode(64-bit sub mode)を前提として説明を進める。 • Pagingとは • メモリ上に構築されたpage table structureをMMU(Memory Management Unit) が解釈し、Linear→Physicalのアドレス変換、保護制御、キャッシュ制御を実行。 • 上記MMU処理の単位である4KBをページと呼ぶ。但しpage tableの指定により 2MB、1GBを1ページとして扱うことも可能。 • ページフレームとは(赤本の定義に準拠) • 特にRAMについて、領域をページサイズ・ページアラインで区切った時の、各ブ ロックを「ページフレーム」と呼ぶ。 • すなわち、カーネルが所謂メモリを有限リソースとして管理する際の最低単位。 7
  • 8.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. struct page • ページフレームに一対一で用意され、種々の情報を格納 • ページディスクリプタとも(赤本などでは)呼ばれる • (有名な話だが)1個のサイズは、キャッシュライン(i7なら64B) に収まるよう保たれており、サイズ拡張は原則論外とされる • (あまり知られてないと思うが)中身は更にdouble word(64bit 環境なら16バイト)x4にアラインするように作られている。
 これは、slubのコードでcmpxchg_doubleとかいう atomic 操作を行うため(らしい) 8
  • 9.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. mem_map • 全RAMページフレームに対応するstruct pageを一 つの配列に格納したもの。 • 牧歌的な実装・・・
 #define __pfn_to_page(pfn) ¥
 (mem_map + ((pfn) - ARCH_PFN_OFFSET)) • ところが、CONFIG_NUMA+CONFIG_X86_64(と いうかCONFIG_SPARSEMEM)では、全メモリ統 一のmem_mapは存在しない。 9
  • 10.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. sparse memoryでの __pfn_to_page() • #define __pfn_to_page(pfn) 
 ({ unsigned long __pfn = (pfn); 
 struct mem_section *__sec = __pfn_to_section(__pfn); 
 __section_mem_map_addr(__sec) + __pfn; 
 }) • 二段テーブル構造 • 1段目:struct mem_sectionのリスト • 2段目 : mem_section::section_mem_map
 ある長さの連続領域(後述するように128MB分)の中のページフレーム に対応するミニmem_mapの役割 • sparseな物理メモリレイアウトに対応。 10
  • 11.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. RAM情報の取得 • __init memblock_x86_fill() • 物理メモリ上の何処がRAMにマップされている か特定する関数 • BIOS(e820)から得たRAM領域情報を使い、
 memblockリストを作成。
 (E820_RAMまたはE820_RESERVED_KERNな e820entry毎に、memblock_add()を呼び出し) 11
  • 12.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. mem_section(離散型mem_map)の
 作成 • void __init sparse_memory_present_with_active_regions(int nid)
 {
 unsigned long start_pfn, end_pfn;
 int i, this_nid;
 
 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, &this_nid)
 memory_present(this_nid, start_pfn, end_pfn);
 } • for_each_…は前頁で作成したmemblockリストをiterationする もの。memory_present()の中では、memblockを128MB長毎に 区切り、それぞれmem_sectionを作成する。 • 128MB = PAGE_SIZE * (2MB / sizeof(struct page))。
 つまり、一つのmem_sectionが保持するミニmem_mapのサイズ がhuge pageに収まるようにしている。 12
  • 13.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 2. NUMA
  • 14.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. NUMAって • NUMA(Non-Uniform Memory Architecture) • CPUからメモリの距離(レイテンシ)が一様でない • 各CPUと各メモリの全対全に特性が定義される? • => No.
 1個以上のCPU群と最大1個の物理メモリレンジからなる nodeを単位として、node間(or同node内)で特性が定義 される。 • x86ではACPIから構成情報を取得する。 14
  • 15.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. ACPIからNUMA情報取得 • __init initmem_init()
 -> __init x86_numa_init()
 -> __init numa_init(init_func=x86_acpi_numa_init) • ACPIからNUMA情報を取得 • SRAT(Static Resource Affinity Table) • SLIT(System Locality Information Table) • 最終的にstruct pglist_data(pg_data_t)をセット アップ 15
  • 16.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. ACPI SRAT • pxm_to_node_map[MAX_PXM_DOMAINS]
 node_to_pxm_map[MAX_NUMNODES] • nodeとACPI proximity domainの双方向マッピング • LinuxではACPI proximity domainをnodeに抽象化
 (可搬性:ACPI以外でNUMAサポートしてるアーキがある(多分)) • __apicid_to_node[MAX_LOCAL_APIC] • APIC ID(=x86アーキ内部でのCPU番号)からnodeへの単方向マッピング • numa_meminfo • 物理メモリ範囲(start+end)とnodeの双方向マッピング
 (この範囲に稠密にRAMがマップされてるとは限らないのでe820情報も使う) 16
  • 17.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. ACPI SLIT • SLIT(System Locality Information Table) • node(proximity domain)間の距離の情報 • 1byte(0 255)で定義される。 • 0 9=予約済、255=node間アクセス不可 • 10 29: 比較的近い(zone_reclaim対象(後述)) 17
  • 18.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. NODE情報の保存 • __init numa_register_memblks() • ACPI SRAT/SLITから得た情報に基づき、 node_data[]を設定 • node_data[]はNUMA_NODE(nid)マクロ経由で 使用される、NUMA情報を格納する構造体 18
  • 19.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. CPUとNODEのマッピング • 先ほど、ACPIから得た情報 • __apicid_to_node[MAX_LOCAL_APIC] • APIC IDからnodeへの単方向マッピング • だがしかし:Linuxにおけるprocessor ID != ACPI ID • processor IDとAPIC IDのマッピング • early_per_cpr(x86_cpu_to_apicid)に格納(別途、APIC周りの初期化処理による) • 上記2種のテーブルをマージして、最終的に • per_cpu(node_map, cpu)を設定する。cpu_to_node()ユーティリティ関数で参照 • processor IDからnode IDへのマッピング。 19
  • 20.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 3. メモリゾーン
  • 21.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zoneとは • zoneとは、物理メモリをアドレスによって分類したもの。 • enum zone_type {
 ZONE_DMA, //<16MB
 ZONE_DMA32, //<4GB
 ZONE_NORMAL, //全部
 ZONE_HIGHMEM, //x86_64では定義しない
 ZONE_MOVABLE, //???
 __MAX_NR_ZONES
 }; • ZONE_MOVABLEって? • migrationによるページ移動を許可する領域。デフォルトでは存在しない。カーネルオプショ ン kernelcore= で設定(ZONE_NORMALのサイズを設定する。但し=0の場合は ZONE_MOVABLEは作られない) • __GFP_MOVABLEを指定した時のみ、当該ゾーンからページを割当てる。 • Memory hot-removeに必須(movableなメモリのみremove可能)。 21
  • 22.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. NUMAノード毎のzone/zonelist • typedef struct pglist_data {
 struct zone node_zones[MAX_NR_ZONES];
 struct zonelist node_zonelists[MAX_ZONELISTS];
 int nr_zones;
 …
 }; • node_zones[] • node配下のzoneのリスト。どのnodeも全てのゾーンを持つ。
 (但し、幾つかの又は全てのnodeが空の場合もある) • node_zonelists[] • nodeに属すCPUがメモリ割当を実行する際に、
 割当を試行する対象となるzoneを、試行する順序で並べたもの。 22
  • 23.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. struct zonelist node_zonelists[] • サイズはCONFIG_NUMAなら2、さもなくば1 • node_zonelists[0] • 実行中CPUが属すNODEから割当可能な全てのzone(任 意のzone)を含むリスト • node_zonelists[1] • 実行中CPUが属すNODE内のzoneのみを列挙したリ スト(__GFP_THISNODEで使用) 23
  • 24.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zonelists[0]の順序 • zonelists[0]内のzoneの順序はsysctlで変更可能。 • zone • Higher zoneから優先して使う方法。ローカルのZONE_DMA32よりもリモート のZONE_NORMALを先に使う。DMA領域温存を優先するポリシー。 • node • 近傍NUMA nodeから優先して使う方法。局所性を優先するポリシー。 • default • ZONE_DMAとZONE_NORMALのサイズを比較し、 zone か node かを自動的 に選択(ZONE_NORMALの割合が十分大きければDMA領域温存を重視し て zone 、小さければ node ) 24
  • 25.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::watermark[NR_WMARK] • ページ割当時に、フリーページ量に応じて動作変更を行う。3種類ある(min < low < high)。 • WMARK_LOW
 zonelistの全zoneでフリーページ量がlowを下回ってると、slowpathへ移行。
 この段階で、kswapdを起床するが、そのページ回収完了は待たずにページ割 当を実行(非同期的ページ回収) • WMARK_MIN
 minも下回っていると、slowpathの延長で自らページ回収(同期的ページ回収) • WMARK_HIGH
 node毎に動作するkswapdは一度起床されると、配下の全zoneのフリーペー ジがhighを超えるまで動作し続ける。 25
  • 26.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::lowmem_reserve[MAX_NR_ZONES] • どのzoneからメモリ割当の試行を開始するかは、GFPフラグで 決まる(大抵はZONE_NORMAL)から。 • 高位zone(e.g. _NORMAL)でのページ割当に失敗して、低位 zone(e.g. _DMA32)でページ割当を試行する際に、watermark に一定量(=reserve)を加算して割当のハードルを上げる。 • z0から割当試行を開始して、z1にfall backしてきた場合、z1- >lowmem_reserve[z0]がreserveになる。 • 同じzone_type(e.g. _NORMAL同士)ではreserveは0。 26
  • 27.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone_watermark_ok() (watermark判定ロジック) • 目的:引数で指定したwatermark値とフリーページ量を比較して、割当可否を判定 • 主要な引数:order(割り当てたいページのオーダ数)、mark(判定に使うwatermark値)、alloc_flags(GFP由来のフラグ) • 処理 1. alloc_flagsに基づきmarkを調整 • ALLOC_HIGH => markを1/2 • ALLOC_HARDER => markを1/4 2. orderサイズのページ割当後のフリーページ総数が、mark+lowmem_reserveを超えているかチェック 3. 更に以下の条件をチェック(フラグメンテーション度合いのチェック) • オーダが1 MAX_ORDER-1のフリーページ総数がmark>>1を超えているか? • オーダが2 MAX_ORDER-1のフリーページ総数がmark>>2を超えているか? • ・・・ • オーダがorder∼MAX_ORDER-1のフリーページ総数がmark>>orderを超えているか? 27
  • 28.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::dirty_balance_reserve • 当該zoneにおいて、dirtyにしないメモリ量。
 全ページから本reserve値を引いた数が、
 dirtyに出来るページ量の限界値となる。 • max(lowmem_reserve) + high_wmark_pagesで算出 /* * Lowmem reserves are not available to * GFP_HIGHUSER page cache allocations and * kswapd tries to balance zones to their high * watermark. As a result, neither should be * regarded as dirtyable memory, to prevent a * situation where reclaim has to clean pages * in order to balance the zones. */ 28
  • 29.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::percpu_drift_mark • マイナーな機能。zone_watermark_ok_safe()でのみ使われる。 • zone_page_state(z, NR_FREE_PAGES)がpercpu_drift_mark を下回っていた場合、
 zone_page_state_snapshot(percpuのNR_FREE_PAGESも加 算する)をfree_pagesとして、__zone_watermark_ok()を呼び 出す。 • percpu_drift_mark==0の時は無効 • page 迫時にpercpuのfree pageも動員する、その閾値を決め るものと見なせる。 29
  • 30.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::pageset • 型 • struct per_cpu_pageset __percpu *pageset; • 各zoneはpercpuのキャッシュを持ち、出来るだけこの キャッシュからページ割当を行う。
 解放時も最初はこのキャッシュへページを追加。 • ページが余ってくるとバディシステムに戻される。 • CPUキャッシュヒット率を高めることが目的。 30
  • 31.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::free_area[MAX_ORDER] • zone毎のバディシステム(後述)。 31
  • 32.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::lruvec • zone毎の、ユーザページ(無名メモリorページキャッシュ)の使用頻度順に並べた LRU(Least Recently Used)リスト。ページ回収で使う。 • enum lru_list {
 " LRU_INACTIVE_ANON = LRU_BASE,
 " LRU_ACTIVE_ANON = LRU_BASE + LRU_ACTIVE,
 " LRU_INACTIVE_FILE = LRU_BASE + LRU_FILE,
 " LRU_ACTIVE_FILE = LRU_BASE + LRU_FILE + LRU_ACTIVE,
 " LRU_UNEVICTABLE,
 " NR_LRU_LISTS
 };
 struct lruvec {
 struct list_head lists[NR_LRU_LISTS];
 struct zone_reclaim_stat reclaim_stat;
 };" • anon/file及びactive/inactiveを個別に管理している。また、ページ回収対象外の (mlockされてるページなど)を走査対象から外すための独立したリストとして unevictableリストも管理される。 32
  • 33.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone::***_pages • spanned_pages • 単にzone_end_pfn - zone_start_pfn。
 holesもreserved pagesも含む。 • present_pages • spanned_pagesからholesを除いたもの。
 reserved pagesは含む • managed_pages • presend_pagesからreserved_pagesも除いたもの。 • ページ資源管理の文脈では普通、これをzoneの総ページとして扱うことになる。 33
  • 34.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 4. ページフレーム割当 4.1 ゾーンアローケータ 4.2 バディアロケータ
  • 35.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 4.1 ゾーンアロケータ
  • 36.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. alloc_pages • alloc_pages()
 -> alloc_pages_current()
 -> get_task_mempolicy()
 -> if MPOL_INTERLEAVE:
 -> alloc_pages_interleave
 (MPOL_INTERLEAVEポリシーでゾーン選択して割当)
 -> else:
 -> __alloc_pages_nodemask()
 -> 初回get_page_from_freelist()
 -> for_each_zone_zonelist_nodemaskループ
 -> 初回はzonelistの中でローカルnode内のzoneから割当を試行
 -> もしダメなら、二回目get_page_from_freelist()
 -> for_each_zone_zonelist_nodemaskループ
 -> 二回目はzonelistの中のzoneから割当を試行
 -> もしダメなら、__alloc_pages_slowpath() 36
  • 37.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. for_each_zone_zonelist_n odemaskループ! 1. zone_dirty_limitを越えてない? • zone内のdirty page cacheの量に閾値がある。溜めすぎるとflush時にシステム止まるため。 2. zone->watermark(ここではlow)を下回ってない? • sysctl -w zone_reclaim_mode=1 した場合のみ、zone_reclaim()を実行。
 でなければこの時点でこのzoneからの割当は諦め • zone_reclaim():
 * Zone reclaim reclaims unmapped file backed pages and
 * slab pages if we are over the defined limits.
 *
 * A small portion of unmapped file backed pages is needed for
 * file I/O otherwise pages read by file I/O will be immediately
 * thrown out if the zone is overallocated. So we do not reclaim
 * if less than a specified percentage of the zone is used by
 * unmapped file backed pages. 3. OKなら、このzoneのバディアロケータへ進む 37
  • 38.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. __alloc_page_slowpath • 簡単に・・・ 1. wake_all_kswapds() 2. if alloc_flags & ALLOC_NO_WATERMARKS:
 __alloc_pages_high_priority() … 緊急用メモリを使ってページを割当 3. __alloc_pages_direct_compact()
 CONFIG_COMPACTION is unsetなら何もしない 4. __alloc_pages_direct_reclaim()
 slow pathの主役っぽい。
 try_to_free_pages()してからget_page_from_freelist()を試行 5. __alloc_pages_may_oom()
 reclaimのprogressが全く無くなった場合に実行する 6. __alloc_pages_direct_compact()
 前回は非同期で、今回は同期的に実行(完了を待つ) 38
  • 39.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. Memory policy • Memory policyは、modeとnodemaskで定義される • mode : MPOL_*** (後述) • nodemask : mode毎に意味が違うが、基本的には割当に(優 先的に)使われるNUMA node群を示すbit mask • 関連システムコール • set_mempolicy(2): set memory policy for a process • mbind(2): set memory policy for a memory range 39
  • 40.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. Memory policy mode • MPOL_PREFERRED • nodemaskには1つのnodeだけ指定可能。ページ割当時は当該nodeか らのアロケーションを試行し、失敗時は近傍のnodeへfallback。 • MPOL_INTERLEAVE • nodemaskに1つ以上のnodeを指定。ページ割当のたびに、初回にアロ ケーションを試行するnodeをround-robin。 • MPOL_BIND • nodemaskに1つ以上のnodeを指定。ページ割当のたびに、node番号 昇順にページ割当を試行。nodemask外のnodeに対しては試行しない。 40
  • 41.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. dirty page flush • c.f. sysctl/vm.txt • 3 triggers • dirty_background_{bytes,ratio}
 dirtyメモリがこのバイト数/割合を超えると、background kernel threadがwrite back開始 • dirty_{bytes,ratio}
 ユーザプロセスのwriteによってこの閾値を超えると、プロセスコンテキストの延長 でwrite back開始 • dirty_expire_centisecs, dirty_writeback_centisecs
 expire_centisecsを経過すると、ページはoldと見なされる。
 oldなページは次回のperiodical write back(周期:writeback_centisecs)でwrite backされる。 41
  • 42.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. zone reclaim • c.f. mm/vmscan.c:3686 • /*
 * Zone reclaim reclaims unmapped file backed pages and
 * slab pages if we are over the defined limits.
 *
 * A small portion of unmapped file backed pages is needed for
 * file I/O otherwise pages read by file I/O will be immediately
 * thrown out if the zone is overallocated. So we do not reclaim
 * if less than a specified percentage of the zone is used by
 * unmapped file backed pages.
 */ • 目的は恐らく・・・ • zonelistを走査してフリーメモリを探し、全滅だと__alloc_pages_slowpathに入るわけ だけど、その前にlocal zoneで回収可能なページの回収を試みる。局所性維持が狙い。 42
  • 43.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. try_to_free_pages, kswapd, compaction • ページ回収系については次回以降でお願いします 43
  • 44.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 4.2 バディアロケータ
  • 45.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. バディシステム(1) • 赤本既読を前提に一言で済ませると、フリーページ のリストを、order毎に分けて管理するもの。
 (orderとはページフレームが幾つ物理的に連続して いるかを2の冪で示したもの。order=nなら2^n個 のページが連続) • higher orderのページはなるべく割り当てないよ うにして、fragmentationを防ぐ。 45
  • 46.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. バディシステム(2) • 調べきれてないので簡単にポイントだけ • バディシステムはstruct zone毎に独立して管理される。
 nodeまたぎやzoneまたぎの連続ページ割当というのはあり得ないということ。 • freelistは、各order 各migrate_typeに作られる。
 migrate_typeはpage migrationとかCMA(continuous memory allocation)に使わ れる種別値。まだ理解できてない・・・ • order=0の場合のみ、per-cpu cacheがある。
 order=0でのアロケーションが失敗すると、per-cpu cacheを充填した上でページを 割り当てる。 • ページは用途に応じてhot or coldがある。これはキャッシュに乗っている可能性が高 い/低いことを示すタームで、割当・解放時に、lruの先頭から/へ割当/解放するか、lru の末尾にするかを切り分けることができる。デフォルトでは割当/解放ともhot扱い。 46
  • 47.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. バディアロケータ • get_page_from_freelist()の最後に実行される buffered_rmqueue()が本体 • バディシステムからメモリを取ってくる • 注:watermarkやdirtylimitをクリアしてから実行 されるわけだが、ロックは取ってるわけではないの で、結局タイミングによっては失敗する可能性あり 47
  • 48.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. buffered_rmqueue() • struct page *buffered_rmqueue(…)
 {
 bool cold = ((gfp_flags & __GFP_COLD) != 0);
 again:
 if (likely(order == 0)) {
 " " pcp = &this_cpu_ptr(zone->pageset)->pcp; /* CPU毎 */
 " " list = &pcp->lists[migratetype]; /* migrate type毎 */
 " " if (list_empty(list)) {
 " " " /* rmqueue_bulk()でバディシステムから補充 */
 " " }
 " " if (cold) /* hot or cold */
 " " " page = list_entry(list->prev, struct page, lru);
 " " else
 " " " page = list_entry(list->next, struct page, lru);
 } else {
 " " page = __rmqueue(); /* バディシステムから直接取得 */
 " }
 " if (prep_new_page(page, order, gfp_flags))
 " " goto again;
 " return page;
 } 48
  • 49.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 5. ページフレーム解放
  • 50.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. order=0なページ解放 • free_hot_cold_page(struct page *page , bool cold) • per-cpuのキャッシュ(zone::pageset)を取り出し、 • hotページは同キャッシュのLRUリストの先頭に、
 coldページは同キャッシュのLRUリストの末尾に追加 • per-cpuキャッシュのフリーページが閾値を超えた場 合は、バディシステムへページを返す。 50
  • 51.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. order>0なページ解放 • free_one_page() • バディシステムへ指定されたorder分のページを 返す • 同orderリスト内で連続ページが作成出来たら、 連結して、zone->free_area[order]から
 zone->free_area[order+1]へ移動 51
  • 52.
    Copyright© 2014 Hitachi,Ltd. All rights reserved. Yokohama Research Lab. 99. 今後 1. ページ回収 2. プロセス空間 3. スラブ(slub, slab, slob) 52