本文基于linux3.10
Fast path:
- get_page_from_freelist – First allocation attempt
using low watermark:
gfp_mask |= __GFP_HARDWALL;
alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET|ALLOC_FAIR;
第一次尝试申请空闲内存,使用LOW水位判断是否足够申请。 - get_page_from_freelist – retry
using low watermark:
gfp_mask |= __GFP_HARDWALL;
alloc_flags &= ~ALLOC_FAIR;
申请失败,判断第一次申请是否包含有ALLOC_FAIR标记,
ALLOC_FAIR希望内核公平(均匀)的从内存域zone中进行内存分配,
如果有那就把该标记拿掉再次尝试一下。
Slow path:
- wake up kswapd
唤醒kswapd线程进行回收内存。 - try alloc pages using min watermark – last chance
alloc_flags = gfp_to_alloc_flags(gfp_mask); — (ALLOC_WMARK_MIN/ALLOC_HARDER/ALLOC_CPUSET)
alloc_flags = ALLOC_WMARK_MIN;
if ((unlikely(rt_task§) && !in_interrupt()) || !wait)
alloc_flags |= ALLOC_HARDER;
if (gfp_mask & _GFP_HIGH)
alloc_flags |= ALLOC_CPUSET;
get_page_from_freelist(…alloc_flags & ~ALLOC_NO_WATERMARKS…)
slow path中尝试更加激进的水位去申请,使用MIN水位,也可能会搭配着ALLOC_HARDER和ALLOC_CPUSET,这两个是更加具有侵略性的申请策略。 - __alloc_pages_high_priority — urgency alloc(ALLOC_NO_WATERMARKS)
get_page_from_freelist(…ALLOC_NO_WATERMARKS…)
如果GFP中判断需要以ALLOC_NO_WATERMARKS来尝试申请,那么就在这里进行,更激进的方式来申请内存。直接忽略水位值来申请。 - alloc faile and can’t wait ---- return failed
如果以上均失败,并且GFP中标志不允许wait,那么此时就要返回申请失败了。 - __alloc_pages_direct_compact — async compact and try alloc
执行内存规整,异步触发,并不会阻塞 - __alloc_pages_direct_reclaim — direct recaim and try alloc
执行内存直接回收,可能会睡眠 - oom killer
执行out of memory操作。 - __alloc_pages_direct_compact — sync compact and try alloc
同步执行规整,可能会阻塞