Linux內存管理概述


(該圖轉自http://bbs.chinaunix.net/thread-2018659-2-1.html,作者Aryang)

下面對各部分進行概述。

Linux進程的線性地址空間(進程虛擬地址空間分佈),0~3G是User地址空間,3~4G是Kernel地址空間。(適用於ARM、X86等,mips按0~2G,2~3G劃分)

關於線性地址佈局,此圖未說明部分:

1.緊接着內核數據區向上是mem_map全局page數組。

2. kernel啓動地址並非是0xC0000000,而是PAGE_OFFSET+TEXT_OFFSET(0x8000),而在這32k大小的空間存放着內核一級頁表數組swapper_pg_dir(每一項一級頁表4個字節,映射1M內存,4G空間共4K項一級頁表,佔用16k內存),頁表在啓動階段setup_arch->paging_init中調用prepare_page_table()和map_lowmem()進行初始化和映射,將在另一篇詳細敘述。

3.內核動態加載驅動模塊so將被load到緊接着MODULES_VADDR~0xC0000000的16M空間。


小於896M的物理內存直接映射到內核3G~3G+896M線性地址空間內,VA=PA-PHYS_OFFSET+PAGE_OFFSET

大約896M的物理內存通過建立各級頁表的方式映射到高端映射區。

每個task在起task_struct內都有一個指針mm指向mm_struct,其控制着該task的所有內存信息,其成員mmap指向vma區鏈表,pgd指向頁全局目錄位置。

切換任務時要爲下一個task裝載其pgd到C2(X86爲cr3)。

在cpu尋址時,mmu將虛擬地址按照2級映射方式,映射到對應物理葉匡的地址偏移上去。

而在內存管理上,系統啓動階段使用的是Bootmem,它是以簡單的bitmap方式(0:未使用,1:已用)。

系統啓動後buddy接手內存管理(以頁爲單位),分爲兩種情況,per_cpu_pageset和free_area,前者用來分配單個頁(在Linux物理內存描述三個層級中有詳細描述),後者用來分配多頁的情況,11個鏈表管理頁塊的大小從2^1~2^11,每個鏈表中又分爲不同遷移類型的子鏈表。

#define MIGRATE_UNMOVABLE     0
#define MIGRATE_RECLAIMABLE   1
#define MIGRATE_MOVABLE       2
#define MIGRATE_PCPTYPES      3 /* the number of types on the pcp lists */
#define MIGRATE_RESERVE       3
#define MIGRATE_ISOLATE       4 /* can't allocate from here */

MIGRATE_TYPES是爲了有效解決內存碎片問題而引入的,將可移動(用戶空間申請的內存可以重新映射)、不可移動(內核空間通常申請的)、可回收(文件映射)等組織在不同的鏈表中,申請內存時按照不同情況在各自類型的鏈表中釋放,如果所在類型內存不足,會fallback到其他類型鏈表繼續分配。在系統初始化完成時全部內存劃分給MOVABLE類型鏈表,當有其他類型需求時再從MOVABLE中釋放生成。

slab分配器是面向對象的分配機制,其建立在buddy基礎之上,細節待另一篇詳述。


框架

(該圖轉自bullbat的博客,強烈推薦該博客http://blog.csdn.net/bullbat/article/details/7166140)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章