- 论坛徽章:
- 1
|
本帖最后由 linuxfellow 于 2015-03-16 05:46 编辑
仔细看了一下内存分配过程。这里的情况应该会用watermark_min/2再分配一次。但是好像没有这么做。
申请2^order内存, 提供内存申请gfp flag:
1:page = __alloc_pages(gfp, order, zonelist);
2:调用 __alloc_pages_nodemask(gfp_mask, order, zonelist, NULL);
3:设置ALLOC_WMARK_LOW标志,水印用watermark_low
alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET|ALLOC_FAIR;
调用_page_from_freelist, 需要 gfp_mask|__GFP_HARDWALL和alloc_flags
page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order,
zonelist, high_zoneidx, alloc_flags,
preferred_zone, classzone_idx, migratetype);
4:如果分配失败,去掉IO,和FS有关的标志
flags &= ~(__GFP_IO | __GFP_FS);
用新的标志,调用__alloc_pages_slowpath进行分配
page = __alloc_pages_slowpath(gfp_mask, order,
zonelist, high_zoneidx, nodemask,
preferred_zone, classzone_idx, migratetype);
水印调整为watermark_low
5: 如果gfp_mask不禁止kswpd,启动kswpd进行回收
if (!(gfp_mask & __GFP_NO_KSWAPD))
wake_all_kswapds(order, zonelist, high_zoneidx,
preferred_zone, nodemask);
6: 加大力度,设置__GFP_HIGH,watermark_min会降到原来的一半
alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH);
7: 对于非阻塞内存请求:
如果请求没有特殊指名__GFP_NOMEMALLOC, 进一步加大力度,设置ALLOC_HARDER。watermark_min会降到原来的1/4
if (!(gfp_mask & __GFP_NOMEMALLOC))
alloc_flags |= ALLOC_HARDER;
对于阻塞内存请求,如果是实时进程,且不在中断上下文,也设置ALLOC_HARDER
(unlikely(rt_task(current)) && !in_interrupt())
alloc_flags |= ALLOC_HARDER;
8:如果请求没有指定__GFP_NOMEMALLOC
如果有指定__GFP_MEMALLOC
如果在软中断服务进程,且进程指定__GFP_MEMALLOC
如果不在中断上下文,且进程指定__GFP_MEMALLOC,或者进程设置了TIF_MEMDIE
直接进行无水印分配
if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) {
if (gfp_mask & __GFP_MEMALLOC)
alloc_flags |= ALLOC_NO_WATERMARKS;
else if (in_serving_softirq() && (current->flags & PF_MEMALLOC))
alloc_flags |= ALLOC_NO_WATERMARKS;
else if (!in_interrupt() &&
((current->flags & PF_MEMALLOC) ||
unlikely(test_thread_flag(TIF_MEMDIE))))
alloc_flags |= ALLOC_NO_WATERMARKS;
}
9:先去掉无水印标志,加大力度正常分配再试一次
/* This is the last chance, in general, before the goto nopage. */
page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist,
high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS,
preferred_zone, classzone_idx, migratetype)
10: 单独处理无水印分配,如果gfp_mask含有__GFP_NOFAIL,进入睡眠,这个过程就一直循环下去
page = get_page_from_freelist(gfp_mask, nodemask, order,
zonelist, high_zoneidx, ALLOC_NO_WATERMARKS,
preferred_zone, classzone_idx, migratetype);
11: 运用前面的标志直接回收内存,direct compact主要处理大页分配,这里关系不大
page = __alloc_pages_direct_compact(gfp_mask, order, zonelist,
high_zoneidx, nodemask, alloc_flags,
preferred_zone,
classzone_idx, migratetype,
migration_mode, &contended_compaction,
&deferred_compaction);
12: 直接回收。。。。。
/* Try direct reclaim and then allocating */
page = __alloc_pages_direct_reclaim(gfp_mask, order,
zonelist, high_zoneidx,
nodemask,
alloc_flags, preferred_zone,
classzone_idx, migratetype,
&did_some_progress);
if (page)
goto got_pg;
/* Check if we should retry the allocation */
pages_reclaimed += did_some_progress;
if (should_alloc_retry(gfp_mask, order, did_some_progress,
pages_reclaimed)) {
/*
* If we fail to make progress by freeing individual
* pages, but the allocation wants us to keep going,
* start OOM killing tasks.
*/
if (!did_some_progress) {
page = __alloc_pages_may_oom(gfp_mask, order, zonelist,
high_zoneidx, nodemask,
preferred_zone, classzone_idx,
migratetype,&did_some_progress);
if (page)
goto got_pg;
if (!did_some_progress)
goto nopage;
}
/* Wait for some write requests to complete then retry */
wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50);
goto retry;
} else {
/*
* High-order allocations do not necessarily loop after
* direct reclaim and reclaim/compaction depends on compaction
* being called after reclaim so call directly if necessary
*/
page = __alloc_pages_direct_compact(gfp_mask, order, zonelist,
high_zoneidx, nodemask, alloc_flags,
preferred_zone,
classzone_idx, migratetype,
migration_mode, &contended_compaction,
&deferred_compaction);
if (page)
goto got_pg;
}
|
|