免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 10093 | 回复: 28

[内存管理] cache/buffer, anon, mmap 三类page的状态和生命周期转换。 [复制链接]

论坛徽章:
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
发表于 2012-05-22 20:00 |显示全部楼层
本帖最后由 embeddedlwp 于 2013-05-06 08:49 编辑

找到 fengguang童鞋的一个slides,share一下

论坛徽章:
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
发表于 2012-05-23 18:54 |显示全部楼层
本帖最后由 embeddedlwp 于 2012-05-23 18:57 编辑

回复 1# blake326


一般的情况,应该首先释放cache/buffer内存。
比如cat 一个文件,page只被引用了一次,所以状态是inactive,referenced。
第一次shrink_inactive_list会将这些page的referenced标志清除。
第二次shrink_inactive_list会将这些page释放。(二次机会)

=============================================================

    在我看的2.6.24的代码中,这个二次机会不一定总会有。shrink_page_list部分代码:

        referenced = page_referenced(page, 1);
                /* In active use or really unfreeable?  Activate it. */
                if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
                                        referenced && page_mapping_inuse(page))
                        goto activate_locked;


/* Called without lock on whether page is mapped, so answer is unstable */
static inline int page_mapping_inuse(struct page *page)
{
        struct address_space *mapping;

        /* Page is in somebody's page tables. */
        if (page_mapped(page))
                return 1;

        /* Be more reluctant to reclaim swapcache than pagecache */
        if (PageSwapCache(page))
                return 1;

        mapping = page_mapping(page);
        if (!mapping)
                return 0;

        /* File is mmap'd by somebody? */
        return mapping_mapped(mapping);
}

也就是说只有被access过,而且这些条件都满足,才能拿到二次机会!

论坛徽章:
0
发表于 2012-05-23 19:35 |显示全部楼层
回复 3# embeddedlwp


    一般的情况,应该首先释放cache/buffer内存。
比如cat 一个文件,page只被引用了一次,所以状态是inactive,referenced。
第一次shrink_inactive_list会将这些page的referenced标志清除。
第二次shrink_inactive_list会将这些page释放。(二次机会)


在看了下page_check_references代码,发现这种情况page会被直接回收的。
buffer/cache并没有相应的pte对应它并是最近访问的pte。
        referenced_ptes = page_referenced(page, 1, sc->mem_cgroup, &vm_flags);
这个返回0,就应该被直接释放。所以说,buffer、cache很容易被释放,只要内存不够了,shrink_inactive_list第一次机会的时候就能够将这些只用了一次的buffer/cache给释放了。
当然,多次访问过的buffer/cache会通过mark_page_accessed从inactive的lru移动到active的lru。


论坛徽章:
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
发表于 2012-05-23 20:14 |显示全部楼层
本帖最后由 embeddedlwp 于 2012-05-23 20:16 编辑

回复 4# blake326


在看了下page_check_references代码,发现这种情况page会被直接回收的。
buffer/cache并没有相应的pte对应它并是最近访问的pte。
        referenced_ptes = page_referenced(page, 1, sc->mem_cgroup, &vm_flags);
这个返回0,就应该被直接释放。所以说,buffer、cache很容易被释放,只要内存不够了,shrink_inactive_list第一次机会的时候就能够将这些只用了一次的buffer/cache给释放了。
当然,多次访问过的buffer/cache会通过mark_page_accessed从inactive的lru移动到active的lru。

==============================================================

看了一下3.4的代码:

int page_referenced(struct page *page,
                    int is_locked,
                    struct mem_cgroup *memcg,
                    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, memcg,
                                                                vm_flags);
                else if (PageAnon(page))
                        referenced += page_referenced_anon(page, memcg,
                                                                vm_flags);
                else if (page->mapping)
                        referenced += page_referenced_file(page, memcg,
                                                                vm_flags);
                if (we_locked)
                        unlock_page(page);

                if (page_test_and_clear_young(page_to_pfn(page)))
                        referenced++;
        }
out:
        return referenced;
}

红的部分在测PG_referenced是否置位,也就是说即使是访问过一次的cache/buffer,这里也会返回1而不是0啊!所以你说的那个红色的部分应该不成立吧!嘿嘿!
当内存紧缺的时候,swap tendency 会 >= 100,此时会从 buffer/cache 和 用户地址空间的页 同时回收!


   

论坛徽章:
0
发表于 2012-05-24 08:40 |显示全部楼层
本帖最后由 blake326 于 2012-05-24 11:11 编辑

回复 5# embeddedlwp


    38的代码跟3.4的差不多。
    我有个疑问:
        if (page_mapped(page) && page_rmapping(page)) {
    对于这个条件,buffer/cache page一般不可能成立吧。

//buffer/cache page一般没有pte指向的。在内核一般kmap,然后拷贝到用户的anon,然后再内核kumap了。
static inline int page_mapped(struct page *page)
{
        return atomic_read(&(page)->_mapcount) >= 0;
}
//反向映射,anon或者文件映射。buffer/cache不可能有这个吧。-----更正一下,这个明显是文件映射的!晕了
static inline void *page_rmapping(struct page *page)
{
        return (void *)((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
}

   更重要的一个问题:
                if (page_test_and_clear_young(page_to_pfn(page)))
                        referenced++;
这个page_test_and_clear_young方法我查了下只有s390上才有定义的。其他架构上都是noop。英文我不太看的懂,你可以看下,貌似说s390的pte跟一般的不一样什么的。还请看了之后,指教指教我啊。


论坛徽章:
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
发表于 2012-05-24 17:05 |显示全部楼层
本帖最后由 embeddedlwp 于 2012-05-24 17:11 编辑

回复 6# blake326

//buffer/cache page一般没有pte指向的。在内核一般kmap,然后拷贝到用户的anon,然后再内核kumap了。
static inline int page_mapped(struct page *page)
{
        return atomic_read(&(page)->_mapcount) >= 0;
}

=====================================
buffer/cache page为什么没有pte指向的呢,buffer cache是用来contain meta data的,page cache使用来contain file data的。
那么mmap把一个文件映射到进程的地址空间,当需要访问文件数据的时候,正是由于这个pte的Present标志位没有设置,所以
会触发page fault,然后到page cache中这个page对应的file对应的radix tree里去找.....
你说的“在内核一般kmap,然后拷贝到用户的anon,然后再内核kumap了。”在哪里看到的啊?


更重要的一个问题:
                if (page_test_and_clear_young(page_to_pfn(page)))
                        referenced++;
这个page_test_and_clear_young方法我查了下只有s390上才有定义的。其他架构上都是noop。英文我不太看的懂,你可以看下,貌似说s390的pte跟一般的不一样什么的。还请看了之后,指教指教我啊。

=====================================
什么英文,怎么没找到啊,不过在x上这个应该为空了哈。那么是不是还差这段我们没有分析?

if (!is_locked && (!PageAnon(page) || PageKsm(page))) {
                        we_locked = trylock_page(page);
                        if (!we_locked) {
                                referenced++;
                                goto out;
                        }
                }


BTW:

既然cache/buffer是文件映射,那么会执行下边这个啦:

else if (page->mapping)
                        referenced += page_referenced_file(page, memcg,
                                                                vm_flags);

论坛徽章:
0
发表于 2012-05-24 17:16 |显示全部楼层
本帖最后由 blake326 于 2012-05-24 17:20 编辑

回复 7# embeddedlwp


    我说的buffer/cache 是指的cat 一个文件,通过系统调用read,而产生的page。并没有包括mmap的文件映射page。虽然这两种page都属于buffer/cache。

因为我说的直接read系统调用的buffer/cache page是最多的。比如说grep xxx . -rn 查找字符串什么的。通过free命令会发现cache会急速的增长。


所以我根据page的回收机制和重要性重新分了下,buffer/cache, annon, mmap三种。

read系统调用涉及到两种 buffer/cache, anon.

对于kernel来说,我说的buffer/cache, mmap 的page都是cache。但是,它们的重要性却不同。回收内存时有点区别。

-------------------------------------------------------------------------------------------------
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)) { //下面都没用了。对于read系统调用产生的cache.buffer
                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) //我说的read系统调用出来的buffer/cache, page_mapped(page)都没有成立,肯定不会走了。
                        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;
}

论坛徽章:
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
发表于 2012-05-24 17:47 |显示全部楼层
本帖最后由 embeddedlwp 于 2012-05-24 17:47 编辑

回复 8# blake326



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)) { //下面都没用了。对于read系统调用产生的cache.buffer
        //这两个条件都成立啊,前者判断引用计数,后者判断是不是反向映射,从page_rmapping的实现来看,它判断的是page->mapping,即相应的
          address_space或anon_vma是否存在,既然是文件映射,那么address_space object肯定存在啦,所以怎么说不会往下执行呢,嘿嘿!


                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) //我说的read系统调用出来的buffer/cache, page_mapped(page)都没有成立,肯定不会走了。
                        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;
}
   

论坛徽章:
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
发表于 2012-05-24 17:50 |显示全部楼层
回复 1# blake326



mmap page:
1. do_linear_fault(),filemap_fault()加入到inactive file lru中。pte accessed被置位.
由于mmap经常存在一次然后读取写入之后就不用的情况。所以page重要性不如anon的page,加入到inactive file lru中。

============================================================

我感觉还有个原因,anon主要是 堆栈这类的,所以回收的时候得swap out到swap area.
如果是file map这类的,直接写回就行啦,如果不脏还不用写。


   

论坛徽章:
0
发表于 2012-05-24 18:09 |显示全部楼层
回复 9# embeddedlwp


          if (page_mapped(page) && page_rmapping(page)) { //下面都没用了。对于read系统调用产生的cache.buffer
        //这两个条件都成立啊,前者判断引用计数,后者判断是不是反向映射,从page_rmapping的实现来看,它判断的是page->mapping,即相应的
          address_space或anon_vma是否存在,既然是文件映射,那么address_space object肯定存在啦,所以怎么说不会往下执行呢,嘿嘿!

>>>>>>>>
       read系统调用产生的buffer/cache page
       page_mapped返回0. page->_mapcount=-1




-----------------------------------------------------------------------
我感觉还有个原因,anon主要是 堆栈这类的,所以回收的时候得swap out到swap area.
如果是file map这类的,直接写回就行啦,如果不脏还不用写。

>>>>>>
必须的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP