02 基础篇 | Page Cache是怎样产生和释放的?

2020-08-17 邵亚方
《Linux 内核技术实战课》
课程介绍


讲述:邵亚方

时长:大小9.04M


你好,我是邵亚方。
上一讲,我们主要讲了“什么是 Page Cache”(What),“为什么需要 Page Cache”(Why),我们这堂课还需要继续了解一下“How”:也就是 Page Cache 是如何产生和释放的。
在我看来,对 Page Cache 的“What-Why-How”都有所了解之后,你才会对它引发的问题,比如说 Page Cache 引起的 load 飙高问题或者应用程序的 RT 抖动问题更加了然于胸,从而防范于未然。
其实,Page Cache 是如何产生和释放的,通俗一点的说就是它的“生”(分配)与“死”(释放),即 Page Cache 的生命周期,那么接下来,我们就先来看一下它是如何“诞生”的。

Page Cache 是如何“诞生”的?

Page Cache 的产生有两种不同的方式:
Buffered I/O(标准 I/O);
Memory-Mapped I/O(存储映射 I/O)。
这两种方式分别都是如何产生 Page ...

展开全文
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。

精选留言

  • 邵亚方
    置顶
    2020-10-11
    课后作业答案: - 为什么第一次读写某个文件,Page Cache 是 Inactive 的? 第一次读取文件后,文件内容都是inactive的,只有再次读取这些内容后,才会把它放在active链表上,处于inactive链表上的pagecache在内存紧张是会首先被回收掉,有很多情况下文件内容往往只被读一次,比如日志文件,对于这类典型的one-off文件,它们占用的pagecache需要首先被回收掉;对于业务数据,往往都会读取多次,那么他们就会被放在active链表上,以此来达到保护的目的。 - 如何让它变成 Active 的呢? 第二次读取后,这些内容就会从inactive链表里给promote到active链表里,这也是评论区里有人提到的二次机会法。 - 在什么情况下 Active 的又会变成 Inactive 的呢? 在内存紧张时,会进行内存回收,回收会把inactive list的部分page给回收掉,为了维持inactive/active的平衡,就需要把active list的部分page给demote到inactive list上,demote的原则也是lru。 - 系统中有哪些控制项可以影响 Inactive 与 Active Page Cache 的大小或者二者的比例? min_free_kbytes会影响整体的pagecache大小;vfs_cache_pressure会影响在回收时回收pagecache和slab的比例; 在开启了swap的情况下,swappiness也会影响pagecache的大小;zone_reclaim_mode会影响node的pagecache大小;extfrag_threshold会影响pagecache的碎片情况。 - 对于匿名页而言,当产生一个匿名页后它会首先放在 Active 链表上,请问为什么会这样子?这是合理的吗? 这是不合理的,内核社区目前在做这一块的改进。具体可以参考https://lwn.net/Articles/816771/。
    展开
    共 1 条评论
    62
  • zwb
    2020-08-21
    第二次机会法,避免大量只读一次的文件涌入 active,在需要回收时又从 active 移动到 inactive lru 链表。场景比如编译内核。

    作者回复: 理解的很正确!

    共 3 条评论
    19
  • x-ray
    2020-09-15
    读这个确实需要对一些linux基础概念有一个了解。前几天刚读的时候,我连VFS都没有一个概念,读起来非常吃力,到第二章就看得云里雾里。这两天找了点视频把一些基础概念熟悉了下,今天再来看的时候,就感觉比较容易理解了。不过我有一个疑问,既然mmap映射的效率更高,为什么不都用这个呢?是因为标准IO无法像文件那样提前加载一块内存到PageCache吗?

    作者回复: mmap与标准io的选择要看具体的场景。很多情况下内存拷贝不会是瓶颈,比如说只写几个或者几百字节的情况下,所以使用哪种都可以;只有在内存拷贝成为瓶颈,比如读写大量文件内容的情况下,比如一次要读写几十上百M,mmap的优势才会提现出来。

    共 3 条评论
    9
  • Geek_162e2a
    2020-08-27
    应用开发者的视角 第一次读写文件,PageCache是inactive的,为什么要这样设计?可能内核底层是采用类似LRU链表的设计来管理PageCache, 如果单纯照搬LRU链表的设计的话,当读大文件的时候会将原本属于热点缓存的PageCache冲刷出去,导致性能波动,因此需要对PageCache进行分类,来避免这个问题,即新读入的文件先进入inactive区域

    作者回复: 理解的很准确 赞!

    共 2 条评论
    8
  • Geek_circle
    2020-08-25
    Memory-Mapped I/O(存储映射 I/O) 是否就是零拷贝的概念呢?

    作者回复: 可以这么理解,它是文件内容的零拷贝。

    
    7
  • 小白哥哥
    2021-05-13
    不认同邵老师对于pagecache产生原因的描述,应用程序调用了write,内核会根据fd当前的fpos计算出写文件操作的文件偏移,然后根据偏移去inode->mapping中找出对应的pagecache页,如果没有的话,分配一页,插入inode->mapping,然后把write调用中的buffer拷贝到pagecache中,这个过程并不会触发page fault。如果是mmap映射文件,然后直接对内存读写,才会触发page fault,进而驱动内核加载文件内容到对应的page cache中。

    作者回复: “这个过程并不会触发page fault”,除了这句话之外,你的其他理解是对的。 inode mapping中如果没有的话,内核会分配一个page,然后将write调用中的buffe拷贝到这个page 中,这个过程叫做pagein,它属于page fault的一种: major fault。你可以通过sar之类的工具来观察这个指标。

    共 6 条评论
    6
  • Geek_162e2a
    2020-08-27
    如何让它变成Active的呢?多读几次文件,达到系统设计的值后,此文件的PageCache会变成热点数据进入Active区域。 在什么情况Active会变成inactive的呢?热点文件太多,且此文件最近没有被读取过,自然就被挤出去了,静态资源服务器,可能会比较经常出现这种情况

    作者回复: 赞!

    
    3
  • 唐江
    2021-05-20
    什么地方讲了inactive 、active 是个数据结构链表啊!不是一个简单的数字吗

    作者回复: proc接口中提供给用户的只是具体的数据项,这些数据项对应到内核代码则是一些数据结构。对于inactive active这两项而言,他们对应内核代码里的lru list。

    
    2
  • 地下城勇士
    2020-08-25
    老师的图是用什么工具画的?感觉以后可以尝试一下

    作者回复: gliffy。chrome有插件。

    共 2 条评论
    2
  • Wade_阿伟
    2021-07-08
    老师您好,看了上面老师的讲述,对存储映射I/O和标准I/O有了一定的理解。但是系统一般什么时候使用存储映射I/O,什么时候使用标准I/O呢?

    作者回复: 标准io相对而言更方便些,在数据量不大的情况下可以使用;如果数据量较大,此时使用存储映射io会更好些。另外一个考虑因为是对内存的精细管理,如果需要管理,比如说把某些数据锁定在内存中,这个时候使用存储映射io更好些。

    
    1