Linux システムでさまざまなメモリの問題に遭遇したことがありますか?メモリリーク、メモリの断片化など。これらの問題は、Linux カーネルのメモリ リサイクル メカニズムを深く理解することで解決できます。
コンピュータ上にどれだけのメモリがあっても十分ではないため、Linux カーネルは、システムがメモリを引き続き使用できるように、めったに使用されないメモリ ページを再利用する必要があります。ページのリサイクルには、ページ ライトバック、ページ交換、ページ破棄の 3 つの方法があります。めったに使用されないページのバッキング ストレージがブロック デバイス (ファイル マッピングなど) の場合、メモリをブロック デバイスに直接同期して解放できます。ページは再利用できます。ページにバッキング ストレージがない場合は、特定のスワップ パーティションにスワップして、再度アクセスしたときにメモリにスワップして戻すことができます。ページのバッキング ストレージがファイルの場合は、ただし、ファイルの内容 (実行可能ファイルなど) はメモリ内で変更できません。現在必要でない場合は、直接破棄できます。
2.1ページフレームのリサイクル
LRU (最も最近使用されていないリンク リスト) は、最近の使用状況に従って配置されています。最も使用されていないものはリンク リストの最後にあり、次のマクロ定義で確認できます:
#define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
各ゾーンには、最近使用したさまざまなページを保存するための 5 つの LRU リンク リストがあります。
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
};
このうち、INACTIVE_ANON、ACTIVE_ANON、INACTIVE_FILE、ACTIVE_FILE の 4 つのリンク リスト内のページがリサイクル可能です。 ANON は匿名マッピング、バッキング ストレージなしを表し、FILE はファイル マッピングを表します。
ページをリサイクルする場合、最初に INACTIVE ページがリサイクルされ、INACTIVE ページが非常に少ない場合にのみ、ACTIVE ページがリサイクルの対象となります。
ページのアクティビティを評価するために、カーネルは 2 つのフラグ PG_referend と PG_active を導入します。なぜ 2 ビット必要なのでしょうか?ページがアクティブかどうかを識別するために PG_active が 1 つだけ使用されると仮定すると、このビットはページがアクセスされたときにセットされますが、いつクリアされるでしょうか?これを行うには、多数のカーネル タイマーを維持する必要があり、このアプローチは失敗する運命にあります。
2 つのフラグを使用して、より洗練されたアプローチを実装できます。中心となるアイデアは、現在のアクティビティ レベルを示すフラグと、最近参照されたかどうかを示すフラグです。次の図は、基本的なアルゴリズムを示しています。
基本的には次の手順があります:
(1) ページがアクティブな場合は、PG_active ビットを設定して ACTIVE LRU リストに保存し、そうでない場合は INACTIVE に保存します。 (2) ページがアクセスされるたびに、PG_referenced ビットが設定されます。mark_page_accessed 関数がこの作業を担当します。
(3) PG_referenced と逆マッピングによって提供される情報は、ページ アクティビティの程度を決定するために使用されます。このビットがクリアされるたびに、ページ アクティビティの程度が検出されます。page_referenced 関数はこの動作を実装します。
(4) 再度、mark_page_accessed を入力します。 PG_referenced が設定されている場合は、page_referenced がチェックされていないことを意味するため、mark_page_accessed が page_referenced よりも頻繁に呼び出され、ページへのアクセスが頻繁に行われていることを意味します。ページが INACTIVE リンク リストにある場合は、ACTIVE に移動します。さらに、PG_active フラグが設定され、PG_referenced がクリアされます。
(5) 逆転送も可能 ページアクティビティが減少した場合、mark_page_accessed を挟まずに page_referenced を 2 回連続で呼び出す場合があります。
メモリ ページへのアクセスが安定している場合、page_referenced と mark_page_accessed の呼び出しは本質的にバランスが取れており、ページは現在の LRU リストに残ります。このソリューションにより、メモリ ページが ACTIVE リンク リストと INACTIVE リンク リストの間で急速に移動することがなくなります。
2.2 スラブ**** キャッシュのリサイクルスラブ キャッシュのリサイクルは比較的柔軟で、shrinker_list に登録されているすべてのメソッドが実行されます。
カーネルは、デフォルトで各ファイル システムの prune_super メソッドを登録します。この関数は、ファイル システムで使用されなくなった dentry キャッシュと inode キャッシュをリサイクルするために使用されます。 Android の lowmemorykiller メカニズムは、プロセスを選択的に強制終了し、プロセスによって使用されているメモリを再利用するメソッドを登録します。
3****ページフレームをリサイクルする方法
其中shrink_page_list是真正回收頁面的過程
#4.1 kswapd
kswapd是核心為每個記憶體node創建的記憶體回收線程,為什麼有了緊缺回收機制還需要週期性回收呢?因為有些記憶體分配是不允許阻塞等待回收的,例如中斷和異常處理程序中的記憶體分配;還有一些記憶體分配不允許啟動I/O存取的。只有少數情況的記憶體缺乏可以完整執行回收過程,所以利用系統空閒時間回收記憶體非常必要。
此函數記錄了上一次均衡運算時所使用的分配order,如果kswapd_max_order大於上一次的值,或是classzone_idx小於上一次的值,則呼叫balance_pgdat再次均衡該記憶體域,否則可以進行短暫休眠,休眠的時間是HZ /10,對於arm(HZ=100)來說,休眠的時間就是1ms。
balance_pgdat均衡操作直到該記憶體域的zone_wartermark_ok為止。
4.2 cache_reap
cache_reap用來回收slab中的空閒對象,如果空閒對象可以還原成一個頁面,則釋放回buddy system。每次呼叫cache_reap會把所有的slab_caches遍歷一遍,之後休眠2*HZ,對於arm(HZ=100)來說,週期就是20ms。
總之,Linux kernel記憶體回收機制是一個非常重要的概念,可以幫助你更好地理解Linux系統中的記憶體管理。如果你想了解更多關於這個概念的信息,可以查看本文提供的參考資料。
#(1)《understanding the linux kernel》
(2)《professional linux kernel architecture》
以上がLinux カーネルのメモリ リサイクル メカニズム: メモリ管理の深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。