zoukankan      html  css  js  c++  java
  • do_try_to_free_pages

    /*
     * This is the main entry point to direct page reclaim.
     *
     * If a full scan of the inactive list fails to free enough memory then we
     * are "out of memory" and something needs to be killed.
     *
     * If the caller is !__GFP_FS then the probability of a failure is reasonably
     * high - the zone may be full of dirty or under-writeback pages, which this
     * caller can't do much about.  We kick the writeback threads and take explicit
     * naps in the hope that some of these pages can be written.  But if the
     * allocating task holds filesystem locks which prevent writeout this might not
     * work, and the allocation attempt will fail.
     *
     * returns: 0, if no pages reclaimed
     *      else, the number of pages reclaimed
     */

    这是个超级重要的函数,是回收页的主逻辑。

    do_try_to_free_pages -> shrink_zones -> shrink_node -->shrink_node_memcg -->

    mem_cgroup_soft_limit_reclaim

    进行内存回收的时候,balance_pgdat和shrink_zones的时候,都是先去回收soft_limit

    只在内存回收的时候起作用,只有全局回收的时候才会去

    mem_cgroup_soft_limit_reclaim --> mem_cgrop_soft_reclaim -->mem_cgroup_shrink_node-->shrink_node_memcg--> ... -->shrink_page_list

    最终都会计入

    所以shrink_nodes是真正的shrink page的地方,在shrink page的地方,只会去回收那些clean的页,在这个函数中先会回收mem soft limit,然后会去刷全局的page

    shrink_zones只在一个地方调用,就是do_write_data_pages,这里是所有直接内存回收的地方,包括page_alloc,包括memcgroup缩容,都是在这里, do_try_to_free_pages这里是,这是直接内存回收的路径,① kwapd_shrink_node--->shrink_node-->shrink_node_memcg

    shrink_node_memcg函数就是所有函数的殊途同归的地方,shrink_node是啥子呢?

    ② node_reclaim-->__node_reclaim-->shrink_node 这个是快速回收方法, shrink_node就是

    ③ do_try_to_free_pages --> shrink_nodes  --> shrink_node

    所以shrink_node从三个地方来,所以地方一是慢速回收,地方二是用do_try_to_free_pages慢速回收,再就是后台回收了,前两者都是全局的回收,do_try_to_free_pages就包括全局回收,也包括cgroup回收啦,mem_cgroup_soft_limit_reclaim就完全是和主流的回收流程并行的一套回收逻辑了。咋说呢?mem_cgroup_soft_limit_recliam的出发点有两个1> balance_pgdat 2>使用在使用shrink_zones的时候,do_try_to_free_pages的时候要用,并且在是在全局回收的时候调用。

    所以我们就知道了,soft_limit_reclaim在什么时候起作用呢?就是在全局内存内存回收的时候。也就是在上图中的1)和3)两条线,机型内存回收时,如果是全局的回收,在调用最后的shrink_node_memcg之前

    shrink_zones直接内存回收

    【疑问一:】那page的lru到底是放在了cgroup的lru列表里,还是放到了全局的lru列表中去呢?

    shrink_node_memcg 函数中,如果没有cgroup,那么就使用pgdat->lruvec全局的lru的全局表,如果否则放到了cgroup的lru表中,啥时候把页放到lru中呢?看函数__page_cache_alloc,中有mem_cgroup_try_charge

    memcg_kmem_charge_memcg,啥时候

    memory_cgroup_commit_charge --> commit_charge ---> unlock_page_lru 是不是所有的lru表并不是所有的页全都在lru表上的呢

    函数mm/filemap.c __add_to_page_cache_locked函数中会charge page:

    lru_cache_add函数是把page增加到lru链表中

    add_to_cache_lru 函数中增加到lru链表中去,

    page-cache增加页:add_to_cache_lru函数中1)__add_to_cache_lru, 2) lru_cache_add

    普通匿名页:lru_cache_add_active_or_unevictable函数中间接调用lru_cache_add

    在lru_cache_add函数之前已经调用过了函数mem_cgroup_commit_charge函数,这个函数中已经把 page->mem_cgroup = memcg; 做了这样的处理了。

    这是在page-cache中,所以肯定的是,lru有全局表有每个cgroup的表,这些页都是分布在不同的表中。

    那么这个page不同的lru列表,shrink的时候是按照LRU表来shrink的,但是页的lru链表是放到不同的cgroup里的,如果遍历这些cgroup表呢?

    /**
     * mem_cgroup_commit_charge - commit a page charge
     * @page: page to charge
     * @memcg: memcg to charge the page to
     * @lrucare: page might be on LRU already
     * @compound: charge the page as compound or small page
     *
     * Finalize a charge transaction started by mem_cgroup_try_charge(),
     * after page->mapping has been set up.  This must happen atomically
     * as part of the page instantiation, i.e. under the page table lock
     * for anonymous pages, under the page lock for page and swap cache.
     *
     * In addition, the page must not be on the LRU during the commit, to
     * prevent racing with task migration.  If it might be, use @lrucare.
     *
     * Use mem_cgroup_cancel_charge() to cancel the transaction instead.
     */

    5423 void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg, bool lrucare, bool compound)

    memory_cgroup_soft_limit在哪里用呢?首先是kwapd_shrink_node函数里,在调用shrink_node之前,会首先回收soft_limit超过阈值的页,再就是在函数shrink_zones中,shirik_zones只在一个地方使用do_try_to_free_pages,在强制内存回收的时候,如果是全局的强制内存回收,还是先想着想着回收内存中,

    【疑问二:为啥干净的页就能够】

    全局管理有个好处,LRU是全局管理,大家一份,但是现在

    void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg,

    shrink_node-> shrink_node_memcg

  • 相关阅读:
    learning.py报错
    Swift与OC的相互调用
    微信小程序地图之逆地理编码
    微信小程序-滑动视图注意事项
    animate.css动画种类
    利用WKWebView实现js与OC交互注意事项
    jquey下eq()的使用注意事项
    如何判断html页面停止滚动?
    git 常见报错
    openresty中http请求body数据过大的处理方案
  • 原文地址:https://www.cnblogs.com/honpey/p/9054150.html
Copyright © 2011-2022 走看看