本文主要是介绍linux内核原理--页高速缓存,回写,页框回收,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.页高速缓存
我们主要分析下磁盘文件的页高速缓存
struct address_space {struct inode *host; struct radix_tree_root page_tree; spinlock_t tree_lock;unsigned int i_mmap_writable;struct prio_tree_root i_mmap; struct list_head i_mmap_nonlinear;spinlock_t i_mmap_lock; unsigned int truncate_count; unsigned long nrpages;pgoff_t writeback_index;struct address_space_operations *a_ops;unsigned long flags; struct backing_dev_info *backing_dev_info;spinlock_t private_lock;struct list_head private_list; struct address_space *assoc_mapping;
} __attribute__((aligned(sizeof(long))));
页高速缓存通过上述结构实现.
每个磁盘文件拥有一个address_space
.page_tree
是一个页框容器.容器内每个页框均存储了来自关联文件指定偏移下的一页数据.
i_mmap
是一个vma
容器.容器内每个vma
均是针对此文件某个区域的一个vma
.
i_mmap_nonlinear
是一个vma
容器.容器内每个vma
采用非线性映射的方式和此文件建立映射.
a_ops
用于提供一组操作集合.以便实现内存,后备存储器两者间的数据交互.
page_tree
是一颗多叉树,叶子节点是代表一个页框的page
指针.linux
下每个节点一般的分叉数是64
.
根据文件尺寸,我们可以计算文件页框数.根据文件页框数可以为其构建这样一颗多叉树,来快速定位指定文件指定页框的page
对象.
假设基树的分叉是4
,那么对于一个文件尺寸在页框[5, 16]
之间的文件对象而言,它的基树高度是2
.利用基树可快速查找文件指定偏移的页框是否已经存在于基树中.
文件对象页高速缓存中的每个页框均位于文件对象的基树内.对于文件中页高速缓存中没缓存的页框,基树中叶子节点相应槽内容为null
.针对节点所有槽均为null
的节点,一般节点会直接移除.相应的上层节点对于槽位置将为null
.
上述是文件尺寸在页框[5, 16]
之间的文件对象只有页框0,1,2,3
位于页高速缓存时其基树的情况示意图.
有了页高速缓存,对文件的读,写,均先通过页高速缓存,这有助于减少和磁盘的直接交互次数.提升IO
效率.
页高速缓存下,还搭配预读机制,以便进一步提升缓存命中率,提升IO
效率.
2.回写
通过文件映射和页高速缓存我们可以读取文件数据,在内存中对其进行修改.
为了保证数据一致性,当文件页在内存被修改后,需要写会磁盘来同步.
linux
提供了两种回写机制.
(1). 通过后台线程定时回写
后台线程定期运行,检测存在脏页时,对脏页执行回写处理.
(2). 通过系统调用显式请求数据同步
如通过fsync
,fsyncdata
来显式请求将文件在内存的脏页刷新到磁盘.
3.页框回收
为了应对物理内存有限下,系统需要分配新的物理内存而可能无法找到可用的空闲物理内存满足分配的场景.
系统需要页框回收机制.
(1). 通过将很少使用的部分物理内存页换出到块设备交换区,我们可以获得更多的空闲内存页.
值的注意的是内核自身使用的物理内存页不会被换出.
(2). 通过将标记为脏的文件映射页执行同步处理,我们可以直接释放这个页框.以便获得更多的空闲内存页.
(3). 通过直接释放非脏的文件映射页,我们可以获得更多的空闲内存页.
linux
可以同时支持多个磁盘交换区,每个交换区可以基于硬盘分区实现,也可基于磁盘文件实现.
在交换区和物理页框之间,类似页高速缓存,存在交换高速缓存结构.
当某个属于匿名映射的物理页框由于页框回收需要写入交换区时,先将其加入相应交换区对象的交换高速缓存结构,在写入完毕后,再从交换高速缓存结构移除.
当某个共享的匿名映射页框由于页框回收需要写入交换区时,先将其加入相应交换区对象的交换高速缓存结构,利用反向映射修改每个使用该页框的页表项,使其指向交换区某位置.在写入完毕,且所有相关进程的页表项均修改完毕后,再从交换高速缓存结构移除.此后,某个进程再次访问此交换页,则需分配页框,页框加入交换高速缓存,执行从交换区读取数据填充页框的操作,在填充完成后,修改进程页表使其指向内存页.只有,所有相关进程均再次访问此交换页,且进程页表均被修改指向内存页后,才可将此页从交换高速缓存结构移除.
交换高速缓存存在的意义是:
每当进程访问某个线性地址,通过页表项获知对应页框位于交换区某位置时,可先尝试访问交换区对象的交换高速缓存,如访问到,则无需执行缓慢的磁盘io
,直接修改进程页表指向交换缓存中页即可.只有交换缓存结构搜索不到,才需执行分配页框,页框添加到交换缓存,执行磁盘io
来填充页框这样的流程.
指的注意的是:
交换区存在的意义在于配合页框回收,逻辑上扩大物理内存.
当换出页位于交换高速缓存期间,页框并未被释放,只有页框换出完成且页框从交换高速缓存结构移除后,页框才能被释放完成回收.
这篇关于linux内核原理--页高速缓存,回写,页框回收的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!