操作系统碎片知识
1. 预读失效和缓存污染是怎么解决的?
常见的 xv6, MySQL, Linux 在文件系统前面都有一层来缓存文件内容,实现对文件的快速访问,这里着重于 Linux ,和 MySQL 一样, linux 也没有采取简单的 LRU 替换策略,这里主要是因为传统的 LRU 可能会导致预读失效和缓存污染两个问题。
预读机制就是根据空间局部性原理,在加载磁盘中的一个页大小的数据的时候,会将相邻的数据页也加载进入 page cache ,但是如果一次性读取大量的数据页,但是他们其实之后并没有被读取,反而浪费了缓存空间,这就是预读失效问题,因此,我们需要尽量减少预读进来的页停留的时间尽量少,这一目的是和 MySQL 一样的。
我们的 Linux 将 LRU 分为了两个链表,活跃页和非活跃页链表,我们会将预读的页加入非活跃页链表,而活跃页则是至少读取过一次的页,非活跃页只有被读取了过一次,才会放入活跃页,否则,就会从非活跃页链表中溢出。
但是与此同时,我们如果一次性读取大量的数据,而这些数据仅仅会读取一次,就放入了活跃页链表,而之前会多次读取的热点数据就被加载的大量数据给淘汰了,但是这些数据仅仅会读取一次,很明显,这是不合理的,所以我们应该提高进入活跃页链表的门槛,在 Linux 中,只有在页被二次访问的时候,才会加入到活跃页链表,而 MySQL 中成为活跃页的要求更加苛刻,需要你访问的持续时间(第一次到最近一次的间隔)超过 1 秒,才能够加入 young 链表中,这也能够很好的减少缓存污染的问题。
2. 讲讲 Page Cache ?
这里不得不提 xv6 中 lock 实验的 buffer cache
, 它用来充当文件系统的缓存,以磁盘块为单位,而我们的 Page Cache
是以页为单位,也是文件系统的缓存,在 linux 中, buffer cache
被合并在了 Page Cache
中。
我们的 Page Cache
在内核中是全局可见的,我们通过系统调用 read
, write
等等都是在内核态中读写 page cache
来实现的,在这种情况下,由于直接读写内存,速度是非常快的,而且减少了磁盘 I/O,而当我们进程崩溃,并不会对文件系统或者 page cache
造成影响,但是如果操作系统崩溃,那就可能会导致数据丢失。
对于操作系统崩溃也有一些要说的,但是总结成一句话就是 log 日志可以保证操作系统的文件系统状态正常,但是无法保证数据不丢失。
最后更新于