kernel-4.9内存回收核心流程

以32位系统为例

内存分配流程调用流程:

alloc_pages()

 -->alloc_pages_node()

  -->__alloc_pages_node()

   -->__alloc_pages()

    -->__alloc_pages_nodemask()

    -->get_page_from_freelist()

在get_page_from_freelist()中,首先会遍历当前zone,按照HIGHMEM->NORMAL的方向进行遍历,判断当前zone是否能够进行内存分配的条件是首先判断free memory是否满足low water mark水位值,如果不满足则进行一次快速的内存回收操作,然后再次检测是否满足low water mark,如果还是不能满足,相同步骤遍历下一个zone,如果两个zone都不满足,get_page_from_freelist()函数返回NULL。

快速内存回收机制:

node_reclaim()

 -->__node_reclaim()-----次处指定每轮进行回收的页面最大值为取需要回收的页面数和32的最大值,快速回收不能进行unmap,writeback操作,回收priority为4,即最多尝试调用shrink_node进行回收的次数为priority值,直到回收到的页数达到需要分配的内存页数或者完成4次循环为止,也就是最多能够回收128页

static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order)
{const unsigned long nr_pages = 1 << order;
………………struct scan_control sc = {//内存回收的条件.nr_to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX),.gfp_mask = memalloc_noio_flags(gfp_mask),.order = order,.priority = NODE_RECLAIM_PRIORITY,.may_writepage = !!(node_reclaim_mode & RECLAIM_WRITE),.may_unmap = !!(node_reclaim_mode & RECLAIM_UNMAP),.may_swap = 1,.reclaim_idx = gfp_zone(gfp_mask),};
……………………if (node_pagecache_reclaimable(pgdat) > pgdat->min_unmapped_pages) {/** Free memory by calling shrink zone with increasing* priorities until we have enough memory freed.*/do {shrink_node(pgdat, &sc);} while (sc.nr_reclaimed < nr_pages && --sc.priority >= 0);//每一轮是否满足条件}
}

 -->shrink_node()-----这里会对系统中存在的每一个memcg对应的node进行一次内存回收操作,然后更新这一次vmpressure扫描和回收的值,直到扫描完所有的memcg或者回收的页面数到足够的页面,在完成所有的memcg的扫描或者回收到最多32页后会调用vmpressure函数根据这一轮内存回收扫描的总页数以及回收到的页数来计算当前内存的压力值,再根据扫描的页数是否大于512个,决定是否将压力传到native进程lmkd确定是否启动lmkd进行进程清理操作

static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc)
{do {
……………………………………memcg = mem_cgroup_iter(root, NULL, &reclaim);do {shrink_node_memcg(pgdat, memcg, sc, &lru_pages);if (memcg)shrink_slab(sc->gfp_mask, pgdat->node_id,memcg, sc->nr_scanned - scanned,lru_pages);//这里会叫lowmemorykiller起来/* Record the group's reclaim efficiency */vmpressure(sc->gfp_mask, memcg, false,sc->nr_scanned - scanned,sc->nr_reclaimed - reclaimed);//更新回收时的扫描和已回收的页面数if (!global_reclaim(sc) &&sc->nr_reclaimed >= sc->nr_to_reclaim) {mem_cgroup_iter_break(root, memcg);break;//回收的页面数达到标准则跳出循环}} while ((memcg = mem_cgroup_iter(root, memcg, &reclaim)));if (global_reclaim(sc))shrink_slab(sc->gfp_mask, pgdat->node_id, NULL,sc->nr_scanned - nr_scanned,node_lru_pages);//这里当memcg不存在时会叫起来lowmemorykillerif (reclaim_state) {sc->nr_reclaimed += reclaim_state->reclaimed_slab;reclaim_state->reclaimed_slab = 0;}/* Record the subtree's reclaim efficiency */vmpressure(sc->gfp_mask, sc->target_mem_cgroup, true,sc->nr_scanned - nr_scanned,sc->nr_reclaimed - nr_reclaimed);//可能会叫起来lmkdif (sc->nr_reclaimed - nr_reclaimed)reclaimable = true;} while (should_continue_reclaim(pgdat, sc->nr_reclaimed - nr_reclaimed,sc->nr_scanned - nr_scanned, sc));
}

 -->shrink


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部