背景
Read the fucking source code!
--By魯迅A picture is worth a thousand words.
--Byゴーリキー
説明:
- カーネルのバージョン:4.14
- ARM64プロセッサ、コンテックス-A53、二核
- ツールを使用してください:Source Insightは3.5、Visioの
1.概要
この記事では説明しmemory compaction
、メモリのデフラグ技術を。
内側と外側の破片の断片に分割されたメモリの断片化:
- 破片で:内部のメモリページの断片;
- 外部の破片:メモリページ間の断片が連続物理ページ割り当ての失敗をもたらすことができます。
memory compaction
これは、ページを移動すると、連続した空きページを取得するための方法を使用している別の場所に移動することができます。メモリの断片化のために、カーネルを定義しmigrate_type
、移行の種類を記述するために使用されます。
MIGRATE_UNMOVABLE
:非リムーバブル、ページに対応するカーネルによって割り当てられました。MIGRATE_MOVABLE
可動、割り当てられたメモリまたはユーザ空間からのファイルに対応します。MIGRATE_RECLAIMABLE
:非リムーバブル、リサイクルを行ってもよいです。
最初memory compaction
の概要図:
図は、に対応しstruct page
、以下に示すような動作、物理メモリの動作:
前回の記事で言及したpageblock
、我々は数字を見zone
領域であるpageblock
スキャンで上下にpageblock
次のようにサイズが(使用されていない定義されているhuge table
バディシステム管理最大ブロック・サイズと一致し、ケースに):
/* If huge pages are not used, group by MAX_ORDER_NR_PAGES */
#define pageblock_order (MAX_ORDER-1)
#define pageblock_nr_pages (1UL << pageblock_order)
まあ、それはそれのさらなる分析が第一印象は、既にある、と。
1.データ構造
1.1 compact_priority
/*
* Determines how hard direct compaction should try to succeed.
* Lower value means higher priority, analogically to reclaim priority.
*/
enum compact_priority {
COMPACT_PRIO_SYNC_FULL,
MIN_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_FULL,
COMPACT_PRIO_SYNC_LIGHT,
MIN_COMPACT_COSTLY_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
DEF_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
COMPACT_PRIO_ASYNC,
INIT_COMPACT_PRIORITY = COMPACT_PRIO_ASYNC
};
この構造は、記述するために使用されるmemory compact
いくつかの異なる方法を:
COMPACT_PRIO_SYNC_FULL/MIN_COMPACT_PRIORITY
:同期で最高の優先度、圧縮、および移行が完了しました。COMPACT_PRIO_SYNC_LIGHT/MIN_COMPACT_COSTLY_PRIORITY/DEF_COMPACT_PRIORITY
:優先順位、同期的に処理された圧縮、非同期移行プロセス。COMPACT_PRIO_ASYNC/INIT_COMPACT_PRIORITY
:最低の優先順位、圧縮、非同期方法への移行。
1.2 compact_result
これは、圧縮処理関数の戻り値の構造を説明するために使用されます。
/* Return values for compact_zone() and try_to_compact_pages() */
/* When adding new states, please adjust include/trace/events/compaction.h */
enum compact_result {
/* For more detailed tracepoint output - internal to compaction */
COMPACT_NOT_SUITABLE_ZONE,
/*
* compaction didn't start as it was not possible or direct reclaim
* was more suitable
*/
COMPACT_SKIPPED,
/* compaction didn't start as it was deferred due to past failures */
COMPACT_DEFERRED,
/* compaction not active last round */
COMPACT_INACTIVE = COMPACT_DEFERRED,
/* For more detailed tracepoint output - internal to compaction */
COMPACT_NO_SUITABLE_PAGE,
/* compaction should continue to another pageblock */
COMPACT_CONTINUE,
/*
* The full zone was compacted scanned but wasn't successfull to compact
* suitable pages.
*/
COMPACT_COMPLETE,
/*
* direct compaction has scanned part of the zone but wasn't successfull
* to compact suitable pages.
*/
COMPACT_PARTIAL_SKIPPED,
/* compaction terminated prematurely due to lock contentions */
COMPACT_CONTENDED,
/*
* direct compaction terminated after concluding that the allocation
* should now succeed
*/
COMPACT_SUCCESS,
};
1.3 migrate_mode
この構造は、記述するために使用されmigrate
、主同期および非同期処理のために、異なるモードで処理。
/*
* MIGRATE_ASYNC means never block
* MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
* on most operations but not ->writepage as the potential stall time
* is too significant
* MIGRATE_SYNC will block when migrating pages
* MIGRATE_SYNC_NO_COPY will block when migrating pages but will not copy pages
* with the CPU. Instead, page copy happens outside the migratepage()
* callback and is likely using a DMA engine. See migrate_vma() and HMM
* (mm/hmm.c) for users of this mode.
*/
enum migrate_mode {
MIGRATE_ASYNC,
MIGRATE_SYNC_LIGHT,
MIGRATE_SYNC,
MIGRATE_SYNC_NO_COPY,
};
1.4 compact_control
compact_control
実行するための構造compact
、時間に対応する2台のスキャナを維持freepages
し、migratepages
最終的にmigratepages
ページのコピーをするためにfreepages
行きます。十分な詳細で具体的なコメント欄ではなく、精巧な。
/*
* compact_control is used to track pages being migrated and the free pages
* they are being migrated to during memory compaction. The free_pfn starts
* at the end of a zone and migrate_pfn begins at the start. Movable pages
* are moved to the end of a zone during a compaction run and the run
* completes when free_pfn <= migrate_pfn
*/
struct compact_control {
struct list_head freepages; /* List of free pages to migrate to */
struct list_head migratepages; /* List of pages being migrated */
struct zone *zone;
unsigned long nr_freepages; /* Number of isolated free pages */
unsigned long nr_migratepages; /* Number of pages to migrate */
unsigned long total_migrate_scanned;
unsigned long total_free_scanned;
unsigned long free_pfn; /* isolate_freepages search base */
unsigned long migrate_pfn; /* isolate_migratepages search base */
unsigned long last_migrated_pfn;/* Not yet flushed page being freed */
const gfp_t gfp_mask; /* gfp mask of a direct compactor */
int order; /* order a direct compactor needs */
int migratetype; /* migratetype of direct compactor */
const unsigned int alloc_flags; /* alloc flags of a direct compactor */
const int classzone_idx; /* zone index of a direct compactor */
enum migrate_mode mode; /* Async or sync migration mode */
bool ignore_skip_hint; /* Scan blocks even if marked skip */
bool ignore_block_suitable; /* Scan blocks considered unsuitable */
bool direct_compaction; /* False from kcompactd or /proc/... */
bool whole_zone; /* Whole zone should/has been scanned */
bool contended; /* Signal lock or sched contention */
bool finishing_block; /* Finishing current pageblock */
};
2.コールプロセス
より細分化になり、上記のようなデータ構造を見て、それの全過程を見てください。
カーネルでは、動作させるための3つの方法がありますmemory compact
:
- 、直接メモリトリガーするためのメモリ割り当て処理では、割り当て要求を満たすことができない
compact
処理。 - 場合には、十分なメモリがない
kcompactd
実行するためにバックグラウンドでデーモンスレッドウェイクアップし、compact
処理は、 - マニュアルトリガー、
echo 1 > /proc/sys/vm/compact_memory
トリガー;
図が来ます:
実際の動作:
cat /proc/pagetypeinfo
次に示すように:
3. compact
処理
処理方法は、以下の図は、おおよそのプロセスを示し、非常に複雑です。
各サブモジュールのための以下の点のより詳細な分析。
compaction_suitable
メモリのデフラグを実行するかどうかを決定し、我々は以下の3つの条件を満たしている必要があります。
- 以上の透かしの値ではなく、十分に大きな空きページブロックに等しいが、アプリケーション・ページを除去し、ページは、アイドル透かし値の数よりも低くなります。
- 無料ページマイナス二回アプリケーションページ(その倍の移行先として十分な空きページがあることを示している以上)、透かし値よりも高いです。
- アプリケーションは
order
より大きいPAGE_ALLOC_COSTLY_ORDER
指数算出断片、fragindex
決定された値に応じて、。
isolate_migratepages
isolate_migratepages
機能は、スキャナの移動pageblock
可動スキャンしたページの単位は、最終ページは、可動に追加されstruct compact_control
た構造のmigratepages
リスト。下図のように:
isolate_freepages
ロジックとisolate_migratepages
同様の、しかし、ページ分離プロセスに、最終加算cc->freepages
リスト。
スキャナがスキャンを完了するために、アイドルと移行スキャナである場合にはときに何をすべきかの2ページのリスト、それは、あるmigrate
操作を。
migrate_pages
- コール
compact_alloc
の機能cc->freepages
空きページ・リストの抽出; - コールの
__unmap_and_move
モバイルページには、無料のページに移動することができます。
_unmap_and_move
逆マッピングに関連する機能だけでなく、ページのキャッシュを時以降で、深さを見て滞在します。この関数は二つの重要な役割:1)を呼び出しtry_to_unmap
、新しい物理アドレスに再マッピングされたアクセスするのに必要なときに古いマッピング関係削除プロセスのページテーブルは、2)を呼び出しmove_to_new_page
、関数は新しい物理ページに古いページを移動します前記アセンブリファイルarch/arm64/lib/copy_page.S
内copy_page
の関数は、コピーを完了します。
compact_finished
compact_finished
機能は、主にチェックするために使用されてcompact
完了です。
compaction_deferred/compaction_defer_reset/defer_compaction
上述の3つの機能とメモリの断片化は延期compact
これらの三つの機能に関連するtry_to_compact_pages
コール。水位アプリケーションページの上に取り出し空きページ数、および移行のバックアップアプリケーションやタイプは、少なくとも十分な空きページがある場合、それを考慮することができるcompact
成功しました。成功がない場合には、に対処するために数回を延期する必要があるかもしれません。
struct zone
次のフィールドに関連する構造:
struct zone {
...
/*
* On compaction failure, 1<<compact_defer_shift compactions
* are skipped before trying again. The number attempted since
* last failure is tracked with compact_considered.
*/
unsigned int compact_considered; //记录推迟次数
unsigned int compact_defer_shift; //(1 << compact_defer_shift)=推迟次数,最大为6
int compact_order_failed; //记录碎片整理失败时的申请order值
...
};