You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Linux 内核实现了一种称为页面缓存(page cache)的磁盘缓存。这个缓存的目标是通过将数据存储在物理内存中来最小化磁盘 I/O,否则这些数据将需要访问磁盘。
为什么要有页面缓存?1.内存访问速度比硬盘快得多。2.时间和空间局部性原理。
缓存方法
页面缓存由 RAM 中的物理页面组成,其内容对应于磁盘上的物理块
For example, when a process issues the read() system call—it first checks if the requisite data is in the page cache. If it is, the kernel can forgo accessing the disk and read the data
directly out of RAM.This is called a cache hit. If the data is not in the cache, called a cache
miss, the kernel must schedule block I/O operations to read the data off the disk.After the data is read off the disk, the kernel populates the page cache with the data so that any subsequent reads can occur out of the cache. Entire files need not be cached
In a write-back cache, processes perform write operations directly into the page cache.The backing store is not immediately or directly updated. Instead, the written-to pages in the page cache are marked as dirty and are added to a dirty list
structpage*page;
interror;
/* allocate the page ... */page=page_cache_alloc_cold(mapping);
if (!page)
/* error allocating memory *//* ... and then add it to the page cache */error=add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
if (error)
/* error adding page to page cache *///Finally, the requested data can be read from disk, added to the page cache, //and returned to the user:error=mapping->a_ops->readpage(file, page);
First, the page cache is searched for the desired page. If it is not in the cache, an entry is allocated and added. Next, the kernel sets up the write request and the data is copied from user-space into a kernel buffer. Finally, the data is written to disk
A radix tree is a type of binary tree.The radix tree enables quick searching for
the desired page, given only the file offset. Page cache searching functions such as find_get_page() call radix_tree_lookup(), which performs a search on the given tree for the given object.
Linux 内核实现了一种称为页面缓存(page cache)的磁盘缓存。这个缓存的目标是通过将数据存储在物理内存中来最小化磁盘 I/O,否则这些数据将需要访问磁盘。
为什么要有页面缓存?1.内存访问速度比硬盘快得多。2.时间和空间局部性原理。
缓存方法
页面缓存由 RAM 中的物理页面组成,其内容对应于磁盘上的物理块
写缓存
一种方法是不使用缓存,但这种方法很少用,因为它不仅无法缓存写操作,而且还会使缓存无效,从而使它们成本高昂。
第二种方法是写操作会自动更新内存缓存和磁盘文件,称为
write-through
,这种方法的好处是保持缓存的一致性——对后备存储同步且有效——而无需使其失效。也很简单。第三种也是Linux采用的是
write-back
。周期地,脏列表中的页面在称为回写的过程中被写回磁盘,使磁盘上的副本与内存缓存保持一致
Cache Eviction
存的最后一部分是从缓存中删除数据的过程,要么为更多相关的缓存条目腾出空间,要么缩小缓存以使更多的 RAM 可用于其他用途
Least Recently Used
缓存驱逐策略试图用他们可以访问的信息来近似透视算法。LRU 驱逐策略需要跟踪每个页面何时被访问(或至少按访问时间对页面列表进行排序)并驱逐具有最旧时间戳的页面(或在排序列表的开头)。然而,LRU 策略的一个特殊失败是许多文件被访问一次,然后再也不会访问。因此,将它们放在 LRU 列表的顶部并不是最佳选择。不适用。
The Two-List Strategy
因此,Linux 实现了 LRU 的修改版本,称为双列表策略。Linux 保留两个列表,而不是维护一个列表,即 LRU 列表:活动列表和非活动列表。仅当页面已经驻留在非活动列表中时被访问,才会将其放置在活动列表中。列表保持平衡:如果活动列表变得比非活动列表大得多,活动列表头部的项目将移回非活动列表,使其可用于驱逐。
Linux Page Cache
页面缓存,顾名思义,是 RAM 中页面的缓存。页面源自对常规文件系统文件、块设备文件和内存映射文件的读写。
address_space对象
页面缓存中的一个页面可以由多个不连续的物理磁盘块组成,Linux 页面缓存旨在缓存任何基于页面的对象,其中包括多种形式的文件和内存映射。 Linux 内核中的其他许多内容一样,address_space 被错误命名。更好的名称可能是 page_cache_entity 或 physical_pages_of_a_file。
address_space
结构定义如下。i_mmap
字段是这个地址空间中所有共享和私有映射的优先级搜索树,i_mmap 字段允许内核有效地找到与此缓存文件关联的映射。nrpages
个页面host
指向对应inode,如果相关对象没有inode,比如swapper,inode为NULLaddress_space操作集
a_ops
字段指向地址空间操作表。定义如下每个后备存储都描述了它如何通过自己的 address_space_operations 与页面缓存交互。例如,ext3 文件系统在 fs/ext3/inode.c 中定义了它的操作.
读操作:首先,Linux内核尝试在页面缓存中查找请求数据。 find_get_page() 方法用于执行此检查;它传递了一个
address_space
和page offset
如果
find_get_page
返回NULL,则分配一个新页面并添加进page cache:写操作:写操作与读操作不同,仅仅标记页面脏
内核会在将来合适的时候调用
writepage()
方法。通用调用路径如mm/filemap.c
如下:因为前面的步骤都是在所有的页面 I/O 操作期间执行的,所以所有的页面 I/O 都保证经过页面缓存。对于写操作,页面缓存充当写的中转站。
Radix树
因为内核必须在启动任何页面 I/O 之前检查页面缓存中页面的存在,所以这种检查必须很快。否则会引起很大的系统消耗。正如你在上一节中看到的,页面缓存是通过 address_space 对象加上一个偏移值来搜索的。每个address_space都有一个唯一的基数树存储为 page_tree。
旧式哈希表
// TODO
Buffer Cache
单个磁盘块也通过块 I/O 缓冲区与页面缓存相关联.
buffer
是单个物理磁盘块的内存表示。页面缓存还通过缓存磁盘块和缓冲块 I/O 操作减少块 I/O 操作期间的磁盘访问。这种缓存称为buffer cache
,属于page cache一种。刷新线程
在页面缓存中写操作是延迟的。当页面缓存中的数据比后备存储中的数据新时,我们称该数据为脏数据。脏页写回在以下场景发生:
当空闲内存低于
dirty_background_ration
时,内核调用wakeup_flusher_threads() 调用以唤醒一个或多个flusher 线程并让它们运行bdi_writeback_all() 函数以开始写回脏页直到下面两个条件满足:周期性回写是很重要的,这是为了确保没有脏页无限期地保留在内存中。在系统启动时,一个定时器被初始化以唤醒一个刷新线程并让它运行 wb_writeback() 函数。然后这个函数写回所有修改时间超过dirty_expire_interval 毫秒前的数据
系统管理员可以在 /proc/sys/vm 或通过 sysctl 设置这些值
笔记本模式
笔记本模式是一种特殊的页面写回策略,旨在通过最大限度地减少硬盘活动并使硬盘驱动器尽可能长时间地保持低速运行来优化电池寿命。通过
/proc/sys/vm/laptop_mode
配置。除了在脏页太旧时执行回写外,刷新线程还搭载任何其他物理磁盘 I/O,将所有脏缓冲区刷新到磁盘。当dirty_expire_interval 和dirty_writeback_int比如说,10 分钟。写回如此延迟,磁盘很少旋转,当它启动时,笔记本模式确保机会得到充分利用erval 设置为大值时,这个模式最有意义。The text was updated successfully, but these errors were encountered: