gcache.page文件mysql清楚_页面缓存(Page Cache)-内存和文件之间的那点事儿(下)...

现在来做一个测验。假设render程序的最后一个进程实例已经退出,会立即释放页面缓存中的scene.dat数据?人们经常这么认为的,但这不是一个好主意。你有没有想到,我们通常在一个程序中创建一个文件,然后退出,然后在另一个程序中要使用该文件。页面缓存也必须处理这种情况。所以内核为什么要删除页面缓存内容呢?请记住,磁盘比RAM慢5个数量级,因此页面缓存命中是一个巨大的胜利。只要有足够的空闲物理内存,缓存就应该被尽可能的使用。因此,它不依赖于特定的进程,而是一个系统范围的资源。如果你运行render进程一周后,发现scene.dat仍然被缓存,这太幸运了!这就是为什么内核缓存的大小会稳步上升,直到达到上限。这并不是因为操作系统是垃圾并占用你的RAM,这实际上是一种良好的行为,因为从某种程度上说,释放物理内存才是一种浪费。

由于页面缓存的存在,当程序调用write()写字节时,只需将其复制到页面缓存中,并将页面标记为dirty。磁盘I/O通常不会立即发生,因此你的程序不会阻塞等待磁盘。不利的一面是,如果计算机崩溃,您的写操作将永远无法完成,因此像数据库事务日志这样的关键文件必须调用fsync()立刻写入到磁盘(但是仍然需要担心驱动器控制器的缓存,也可能造成并不会立刻写入到物理磁盘)。另一方面,读取通常会阻塞程序,直到数据可用为止。内核使用预先加载技术来缓解这个问题,其中一个例子是提前读取,内核将几个页面预加载到页面缓存中,等待你的读取。你可以通过调整内核的一些选项来调整预先加载行为,可以控制顺序读取文件还是随机读取文件。Linux确实对内存映射文件进行预读,但我不确定Windows是否如此。最后,可以在Linux中使用O_DIRECT绕过页面缓存,或者在Windows中使用NO_BUFFERING绕过页面缓存,这是数据库软件经常做的事情。

文件映射可以是私有的或共享的。这是针对内存中的内容所做的更新:在私有映射中,更新不提交到磁盘或使其他进程可见,而在共享映射中,更新是可见的。内核使用页表项启用的写时复制机制来实现私有映射。在下面的例子中,render和render3d都私有映射了文件scene.dat。render然后写入它的虚拟内存区域中的映射文件:

上面所示的只读页表项并不意味着映射是只读的,它们只是在最后一刻共享物理内存的内核实现技巧。你可以看到“private”是多么的不恰当,只要记住它只适用于更新,读取不是私有的,也是共享的。这种设计的结果是,通过映射文件的虚拟页面可以反映出有其他程序对该文件做了更改。一旦写时复制完成,其他人的更改将不再可见。内核不能保证这种行为,但它是在x86中得到的,(是通过硬件方式实现的?这里不太明白)从API的角度来看是有意义的。相比之下,共享映射仅仅映射到页面缓存,仅此而已。更新对于其他进程是可见的,并最终保存在磁盘中。最后,如果上面的映射是只读的,那么页面错误将触发段错误,而不是写入时的复制错误。

动态加载的库通过文件映射到程序的地址空间。这没有什么神奇的,它是同样的私有文件映射。下面的示例展示了两个运行实例部分地址空间中的文件映射,以及物理内存使用情况,以便我们将上述许多概念联系在一起。

关于内存基础的3部分系列文章到此结束。我希望这个系列是有用的,并为你提供了Linux内核内存管理的宏观机制。

--END

这3部分汇总如下:由于本人水平有限,翻译必然有很多不妥的地方,欢迎指正。

同时,欢迎关注下方微信公众号,一起交流学习:)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值