頁框分配器在慢速分配中包括內存碎片化整理和內存回收,代碼以下:linux
static inline struct page *
__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
struct alloc_context *ac)
{
page = __alloc_pages_direct_compact(gfp_mask, order,
alloc_flags, ac,
INIT_COMPACT_PRIORITY,
&compact_result);
......
page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,
&did_some_progress);
......
}
出於篇幅設計,此次咱們只講內存的碎片化整理,下文再講內存回收。web
什麼是內存碎片化
Linux物理內存碎片化包括兩種:內部碎片化和外部碎片化。算法
內部碎片化:微信
指分配給用戶的內存空間中未被使用的部分。例如進程須要使用3K bytes物理內存,因而向系統申請了大小等於3Kbytes的內存,可是因爲Linux內核夥伴系統算法最小顆粒是4K bytes,因此分配的是4Kbytes內存,那麼其中1K bytes未被使用的內存就是內存內碎片。編輯器
外部碎片化:flex
指系統中沒法利用的小內存塊。例如系統剩餘內存爲16K bytes,可是這16K bytes內存是由4個4K bytes的頁面組成,即16K內存物理頁幀號#1不連續。在系統剩餘16K bytes內存的狀況下,系統卻沒法成功分配大於4K的連續物理內存,該狀況就是內存外碎片致使。url
碎片化整理算法
Linux內存對碎片化的整理算法主要應用了內核的頁面遷移機制,是一種將可移動頁面進行遷移後騰出連續物理內存的方法。spa
假設存在一個很是小的內存域以下:藍色表示空閒的頁面,白色表示已經被分配的頁面,能夠看到如上內存域的空閒頁面(藍色)很是零散,沒法分配大於兩頁的連續物理內存。.net
下面演示一下內存規整的簡化工做原理,內核會運行兩個獨立的掃描動做:第一個掃描從內存域的底部開始,一邊掃描一邊將已分配的可移動(MOVABLE)頁面記錄到一個列表中:另外第二掃描是從內存域的頂部開始,掃描能夠做爲頁面遷移目標的空閒頁面位置,而後也記錄到一個列表裏面:等兩個掃描在域中間相遇,意味着掃描結束,而後將左邊掃描獲得的已分配的頁面遷移到右邊空閒的頁面中,左邊就造成了一段連續的物理內存,完成頁面規整。設計
碎片化整理的三種方式
static struct page *
__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
enum compact_priority prio, enum compact_result *compact_result)
{
struct page *page;
unsigned int noreclaim_flag;
if (!order)
return NULL;
noreclaim_flag = memalloc_noreclaim_save();
*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
prio);
memalloc_noreclaim_restore(noreclaim_flag);
if (*compact_result <= COMPACT_INACTIVE)
return NULL;
count_vm_event(COMPACTSTALL);
page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
if (page) {
struct zone *zone = page_zone(page);
zone->compact_blockskip_flush = false;
compaction_defer_reset(zone, order, true);
count_vm_event(COMPACTSUCCESS);
return page;
}
count_vm_event(COMPACTFAIL);
cond_resched();
return NULL;
}
這也是上面memory compaction算法的代碼實現。
在linux內核裏一共有3種方式能夠碎片化整理,咱們總結以下:
這裏就不展開源碼的解析了,有了宏觀的理解而後再去網上搜下具體實現細節相信不是什麼難事,OK,咱們進入下面的文章內容:內存回收(memory reclaim)。
本文分享自微信公衆號 - 人人都是極客(rrgeek)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。