免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 7020 | 回复: 27
打印 上一主题 下一主题

[内存管理] shrink_inactive_list的page_check_references疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-21 10:55 |只看该作者 |倒序浏览
本帖最后由 blake326 于 2012-05-21 10:57 编辑

2.6.38 kernel
shrink_inactive_list()主要三个步骤:
  1. 获取一组待回收page到page_list。
  isolate_pages_global(nr_to_scan, &page_list, &nr_scanned, sc->order, sc->reclaim_mode & RECLAIM_MODE_LUMPYRECLAIM ? ISOLATE_BOTH : ISOLATE_INACTIVE,
zone, 0, file);
  2. 调用shrink_page_list回收这组page。无法回收的保存在page_list里面。
          nr_reclaimed = shrink_page_list(&page_list, zone, sc);
  3. 将不能回收的page根据active标志放回相应的lru中。
          putback_lru_pages(zone, sc, nr_anon, nr_file, &page_list);
         
         
  问题再shrink_page_list里面:
          while (!list_empty(page_list)) {
                  循环对每个page分别处理。
                 
                  检查page是否应该回收。
                          references = page_check_references(page, sc);
                switch (references) {
                case PAGEREF_ACTIVATE:
                        goto activate_locked;
                case PAGEREF_KEEP:
                        goto keep_locked;
                case PAGEREF_RECLAIM:
                case PAGEREF_RECLAIM_CLEAN:
                        ; /* try to reclaim the page below */
                }
               
                反向映射,释放pte和page的映射。
               
                                if (page_mapped(page) && mapping) {
                        switch (try_to_unmap(page, TTU_UNMAP)) {
                        case SWAP_FAIL:
                                goto activate_locked;
                        case SWAP_AGAIN:
                                goto keep_locked;
                        case SWAP_MLOCK:
                                goto cull_mlocked;
                        case SWAP_SUCCESS:
                                ; /* try to free the page below */
                        }
                }

                  脏页处理。
                                  if (PageDirty(page)) {
                        nr_dirty++;

        }
       
        看page_check_references的代码,如果是用户的匿名page或者映射文件的page,referenced_ptes肯定大于1,导致page_check_references必定返回PAGEREF_KEEP或者PAGEREF_ACTIVATE。
        从而无法释放该page,放回到相应的lru中。那么shrink_page_list后面的反向映射什么时候才有机会执行呢?匿名page,映射page怎样才能释放呢?
        static enum page_references page_check_references(struct page *page,
                                                  struct scan_control *sc)
{
        int referenced_ptes, referenced_page;
        unsigned long vm_flags;

        referenced_ptes = page_referenced(page, 1, sc->mem_cgroup, &vm_flags);
        referenced_page = TestClearPageReferenced(page);

        /* Lumpy reclaim - ignore references */
        if (sc->reclaim_mode & RECLAIM_MODE_LUMPYRECLAIM)
                return PAGEREF_RECLAIM;

        if (vm_flags & VM_LOCKED)
                return PAGEREF_RECLAIM;

        if (referenced_ptes) {
                if (PageAnon(page))
                        return PAGEREF_ACTIVATE;
       
                SetPageReferenced(page);

                if (referenced_page)
                        return PAGEREF_ACTIVATE;

                return PAGEREF_KEEP;
        }

        /* Reclaim if clean, defer dirty pages to writeback */
        if (referenced_page && !PageSwapBacked(page))
                return PAGEREF_RECLAIM_CLEAN;

        return PAGEREF_RECLAIM;
}

论坛徽章:
0
2 [报告]
发表于 2012-05-21 11:18 |只看该作者
没有短消息权限啊!

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
3 [报告]
发表于 2012-05-21 11:36 |只看该作者
本帖最后由 embeddedlwp 于 2012-05-25 21:43 编辑

回复 2# blake326





   

论坛徽章:
1
双鱼座
日期:2013-08-28 13:47:26
4 [报告]
发表于 2012-05-21 11:54 |只看该作者
The page_referenced( ) function, which is invoked once for every page scanned by the PFRA, returns 1 if either the PG_referenced flag or some of the Accessed bits in the Page Table entries was set; it returns 0 otherwise. This function first checks the PG_referenced flag of the page descriptor; if the flag is set, it clears it. Next, it makes use of the object-based reverse mapping mechanism to check and clear the Accessed bits in all User Mode Page Table entries that refer to the page frame.

论坛徽章:
0
5 [报告]
发表于 2012-05-21 12:14 |只看该作者
回复 4# firkraag


    现在的page_referenced好像不是你说的意思了吧?
从代码看就是映射的pte数目。
/**
* page_referenced - test if the page was referenced
* @page: the page to test
* @is_locked: caller holds lock on the page
* @mem_cont: target memory controller
* @vm_flags: collect encountered vma->vm_flags who actually referenced the page
*
* Quick test_and_clear_referenced for all mappings to a page,
* returns the number of ptes which referenced the page.
*/
int page_referenced(struct page *page,
                    int is_locked,
                    struct mem_cgroup *mem_cont,
                    unsigned long *vm_flags)
{
        int referenced = 0;
        int we_locked = 0;

        *vm_flags = 0;
        if (page_mapped(page) && page_rmapping(page)) {
                if (!is_locked && (!PageAnon(page) || PageKsm(page))) {
                        we_locked = trylock_page(page);
                        if (!we_locked) {
                                referenced++;
                                goto out;
                        }
                }
                if (unlikely(PageKsm(page)))
                        referenced += page_referenced_ksm(page, mem_cont,
                                                                vm_flags);
                else if (PageAnon(page))
                        referenced += page_referenced_anon(page, mem_cont,
                                                                vm_flags);
                else if (page->mapping)
                        referenced += page_referenced_file(page, mem_cont,
                                                                vm_flags);
                if (we_locked)
                        unlock_page(page);
        }
out:
        if (page_test_and_clear_young(page))
                referenced++;

        return referenced;
}

论坛徽章:
1
双鱼座
日期:2013-08-28 13:47:26
6 [报告]
发表于 2012-05-21 13:10 |只看该作者
本帖最后由 firkraag 于 2012-05-24 19:37 编辑

这是ulk3中的原文,叫page_referenced的有个是宏也有个是函数,函数返回的是引用过该页的页表项数目。是否引用过要看页表项的accessed.宏定义是没定义CONFIG_MMU时起作用的,与TestClearPageReferenced等效。

论坛徽章:
0
7 [报告]
发表于 2012-05-21 13:36 |只看该作者
本帖最后由 blake326 于 2012-05-21 13:40 编辑
firkraag 发表于 2012-05-21 13:10
这是ulk3中的原文,叫page_referenced的有个是宏也有个是函数,函数返回的是引用过该页的页表项数目。否引用 ...



vmscan.c中调用的是函数的返回pte数目的。
很明显CONFIG_MMU定义了。
我也在里面打了日志看过了,确实调用的是返回pte数目的page_referenced。

问题,就是page_referenced返回pte数目的话,匿名page,映射page,大于1的话怎样释放呢?
我在page_referenced函数里面打印之后发现,绝大部分它返回0,少数1,也有2以上的。

我正在看ulk3中,觉得有些东西还是过时了的。

论坛徽章:
1
双鱼座
日期:2013-08-28 13:47:26
8 [报告]
发表于 2012-05-21 14:24 |只看该作者
page_referenced会把pte的accessed位清零。通过反向映射找到所有的pte。

论坛徽章:
0
9 [报告]
发表于 2012-05-21 14:59 |只看该作者
本帖最后由 blake326 于 2012-05-21 15:00 编辑
firkraag 发表于 2012-05-21 14:24
page_referenced会把pte的accessed位清零。通过反向映射找到所有的pte。



我的问题就是在shrink_page_list中,假如有个page是anon的,并且也有pte指向它。那么page_check_references的时候,因为page_referenced会返回>0, 所以page_check_references就会返回PAGEREF_ACTIVATE,那么该anon页就无法释放,重新加入到active lru中。

问题就是如果这样的话,anon的page或者映射的page怎样释放的呢?


另外:
page_referenced会把pte的accessed位清零。这个我也没有找到在哪做的。

论坛徽章:
1
双鱼座
日期:2013-08-28 13:47:26
10 [报告]
发表于 2012-05-21 15:16 |只看该作者
page_referenced返回值是否为0不是该页有无pte指向,而是该页是否最近被访问过。


清0:
page_referenced()->page_referenced_ksm()/page_referenced_anon()/page_referenced_file()-> page_referenced_one()->ptep_clear_flush_young()-> ptep_test_and_clear_young()->  test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP