【Linux】Linux Page Cache页面缓存的原理

news2024/11/18 15:46:28

Page cache(页面缓存)是计算机操作系统中的一种机制,用于将频繁访问的数据从磁盘存储到内存中,以便更快地访问。当程序从磁盘请求数据时,操作系统会检查该数据是否已经存在于页面缓存中。如果存在,数据可以直接从内存中获取,这比从磁盘访问要快得多。如果数据不在页面缓存中,它将从磁盘中获取并存储在缓存中供将来使用。

既然Page Cache是一种缓存,那么缓存必然带来以下问题:

  1. 占用内存多大空间?
  2. 内存空间满了怎么办,淘汰策略?
  3. 内存中的数据何时写入磁盘?
  4. 数据如何持久化、一致性如何保障?
  5. 内存中的数据是否会丢失?
  6. 持久化的触发时机?

page与Page Cache的关系

从磁盘中读取文件后写入Page Cache中,是将整个文件都写入呢,还是只写用到的那一部分?

page是内存管理分配的基本单位,Page Cache由多个page构成。page在操作系统中通常为4KB大小(32bits/64bits),而 Page Cache的大小则为4KB的整数倍。

操作系统为基于Page Cache的读缓存机制提供预读机制(PAGE_READAHEAD),例如用户线程仅仅请求读取磁盘上文件A的offset为0-3KB范围内的数据,由于磁盘的基本读写单位为block(4KB),于是操作系统至少会读0-4KB的内容,这恰好可以在一个page中装下。

但是操作系统出于局部性原理会选择将磁盘块offset[4KB,8KB)、[8KB,12KB)以及[12KB,16KB)都加载到内存,于是额外在内存中申请了3个page。

下面我们用一个例子来演示一下:

准备一个文本文件ooxx.txt,大小为,需大于4*4=16k:

$ ll ooxx.txt
-rw-rw-r-- 1 vagrant vagrant 41211 Dec 29 05:45 ooxx.txt

使用read命令读取ooxx.txt文件的第一行:

$ read a < ooxx.txt

$ echo $a
bash

那么ooxx.txt前4页的内容将会被缓存在Page Cache中,我们可以使用hcache命令来查看查询文件或者目录有多少页被载入Page Cache中:

$ hcache ooxx.txt
+----------+----------------+------------+-----------+---------+
| Name     | Size (bytes)   | Pages      | Cached    | Percent |
|----------+----------------+------------+-----------+---------|
| ooxx.txt | 41211          | 11         | 4         | 036.364 |
+----------+----------------+------------+-----------+---------+

我们可以看到实际上内核使用readahead机制完成了16KB数据的读取,并放入了Page Cache中。

缺页中断

磁盘的数据怎么写入Page Cache?

操作系统以page为单位管理内存,当进程发现需要访问的数据不在内存时,操作系统可能会将数据以页的方式加载到内存中。上述过程被称为缺页中断,当操作系统发生缺页中断时,就会通过系统调用将page再次读到内存中。

缺页中断的作用

缺页中断是内存管理中的重要机制,具有以下重要作用:

  1. 页面调入内存:当应用程序访问的页面不在内存中时,缺页中断会触发操作系统将缺失的页面从磁盘加载到内存中。这样做的好处是,不需要将整个文件或数据集一次性全部加载到内存中,而是按需加载,只加载应用程序实际需要的页面。这样可以节省磁盘I/O开销,避免了无谓的磁盘读取操作,提高了系统的性能。

  2. 页面替换策略:当内存中的页面已满时,如果应用程序访问一个新的页面,操作系统需要选择一个页面进行替换,将其换出到磁盘上,为新的页面腾出空间。缺页中断提供了一个时机,让操作系统可以根据页面替换算法选择合适的页面进行替换,以保证内存中的页面是最有用的页面,提高内存的利用率。

  3. 延迟写策略:在写回策略下,当应用程序对一个脏页进行写操作时,脏页的写回操作不会立即进行,而是推迟到后续的某个时刻进行。这样可以将多次写操作合并为一次写操作,减少了磁盘写入的次数,降低了磁盘I/O开销。

  4. 页面预读取:为了进一步减少磁盘I/O开销,操作系统可以利用缺页中断的时机进行页面预读取。当应用程序访问一个页面时,操作系统可以预先加载一些相邻的页面到内存中,以提前满足应用程序的访问需求。这样可以减少后续的缺页中断和磁盘读取操作,提高了系统的响应速度。

  5. 权限检查和处理:缺页中断还可以用于检查应用程序对页面的访问权限。操作系统可以根据页面的访问权限(例如只读、读写等)来判断应用程序的访问是否合法,并根据需要进行相应的处理。

缺页中断的处理流程

当发生缺页中断时,操作系统会按照以下步骤来处理:

  1. 中断处理程序:当发生缺页中断时,CPU会暂停当前应用程序的执行,并跳转到操作系统的中断处理程序。这个中断处理程序负责处理缺页中断。

  2. 中断处理程序的执行:中断处理程序会首先保存当前应用程序的上下文信息,包括寄存器的值和程序计数器等。然后,它会根据缺页中断的原因进行相应的处理。

  3. 页面调入内存:如果缺页中断是由于应用程序访问的页面不在内存中引起的,操作系统会触发页面调入内存的过程。它会根据页面表中的信息,确定需要调入的页面的位置和大小,并从磁盘上读取相应的页面数据。

  4. 磁盘I/O操作:在页面调入内存的过程中,操作系统会进行磁盘I/O操作,将需要的页面数据从磁盘读取到内存中。这包括了磁盘寻道、读取数据和数据传输等操作。

  5. 更新页表:当页面数据成功加载到内存中后,操作系统会更新页表,将该页面的状态设置为已加载,并将页面的物理地址映射到对应的虚拟地址。

  6. 恢复上下文和重新执行应用程序:当页面调入内存完成后,中断处理程序会恢复之前保存的应用程序的上下文信息,并将控制权返回给应用程序。应用程序会继续执行之前被中断的指令,但这次访问的页面已经在内存中了,不会再触发缺页中断。

Page Cache的工作原理

Page Cache的工作原理如下:

  1. 当应用程序打开一个文件并读取其中的数据时,操作系统会将文件的内容读取到内存中,并将其缓存为一个或多个页(通常是4KB大小的页)。

  2. 这些缓存的页被存储在一个被称为Page Cache的内存区域中,它是内核管理的一部分。

  3. 当应用程序再次访问相同的文件时,操作系统首先检查Page Cache中是否存在这些页的副本。如果存在,操作系统会直接从Page Cache中返回数据,而不需要再次访问磁盘。

  4. 如果应用程序对文件进行写操作,数据会被写入到Page Cache中的脏页(dirty page)。脏页表示该页的内容已经被修改,但还没有写回到磁盘。

  5. 当系统内存压力较大或需要释放内存时,内核会触发缓存刷新(cache flushing)操作,将脏页从Page Cache写回到磁盘中。

Page Cache的回写策略

回写策略是为了确保缓存数据的一致性和避免数据丢失而设计的。当Page被标记为dirty时,表示该Page中的数据已经被修改过,这些数据需要被写回到磁盘上的,Linux提供了以下两种回写策略:

  • Write Through(写穿):向用户层提供特定接口,应用程序可主动调用接口来保证文件一致性;

  • Write back(写回):系统中存在定期任务(表现形式为内核线程),周期性地同步文件系统中文件脏数据块,这是默认的 Linux一致性方案;

Write Through写穿

Write Through(写透)是将数据写入Page Cache后,立即将数据写入磁盘设备。这样可以确保数据在发生故障或系统崩溃时不会丢失,因为数据已经被持久地写入磁盘。

在JAVA中使用如下的代码实现Write Through写穿:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class WriteThroughTest {
    public static void main(String[] args) throws IOException {
        File file = new File("/home/vagrant/testfileio/ooxx.txt");
        FileOutputStream out = new FileOutputStream(file);
        out.write("hello".getBytes(StandardCharsets.UTF_8));
        out.getFD().sync(); // 立即刷入磁盘
    }
}

我们可以使用strace命令追踪上面程序执行过程中产生的系统调用:

openat(AT_FDCWD, "/home/vagrant/testfileio/ooxx.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
fstat(4, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
write(4, "hello", 5)                    = 5
fsync(4)                                = 0
close(4)

可以系统调用中包含fsync,该命令会把文件描述符fd引用的文件修改过的元数据和数据立即写回到存储设备。

Write back写回

在Write Back模式下,写入操作只会将数据写入Page cache,并不立即写入磁盘设备。而是在后续的时间点或特定条件下,将脏页(已被修改但尚未写入磁盘)批量写回磁盘。

在JAVA中使用Write back写回只需要将上面例子中的立即刷入磁盘代码注释即可:

// out.getFD().sync()

这种回写策略下,数据的一致性完全依赖操作系统的自身机制,那么操作系统何时将Page Cache中的脏页数据写入磁盘中呢?

Page Cache写回时机

Linux内核提供了以下参数来优化Page Cache的性能和行为,我们可以通过这些参数来窥探Page Cache的写回时机。

$ sudo sysctl -a | grep "dirty"
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirtytime_expire_seconds = 43200

具体参数说明:

  • vm.dirty_background_bytes:设置了系统内存中可以保持脏数据的最大字节数。当系统内存中的脏数据超过这个值时,Linux会开始触发后台刷新(异步刷新)将脏数据写入磁盘。

  • vm.dirty_background_ratio:设置了系统内存中可以保持脏数据的最大比例,默认为10%。

  • vm.dirty_bytes:设置了系统内存中允许累积的脏数据的最大字节数。当脏数据超过这个值时,Linux会触发前台刷新(同步刷新),直到将脏数据写入磁盘为止。

  • vm.dirty_ratio:设置了系统内存中允许累积的脏数据的最大比例,默认为20%。

  • vm.dirty_expire_centisecs:该参数指定了脏数据在内存中能够存活的时间,单位为百分之一秒。当脏数据在内存中超过这个时间后,系统会将其异步写入磁盘中,默认值为3000(30秒)。

  • vm.dirty_writeback_centisecs:表示系统在多长时间内进行一次脏数据的后台写回操作。它的单位是百分之一秒(centiseconds),默认值为500,即系统每5秒钟进行一次后台写回操作。

  • vm.dirtytime_expire_seconds:代表内存中脏数据的允许存储时间,单位为秒。当脏数据在内存中存储的时间超过这个时间,系统会将其写入磁盘,以释放内存。

跟pagecache相关的系统调用

内核提供了下面这些把Page Cache中内容写入磁盘的系统调用:

  • sync:将所有未写的系统缓冲区数据写入磁盘,不需要带任何参数。

  • syncfs:syncfs需要一个文件描述符,只将文件描述符指向的文件相关的文件系统的缓冲区数据写入磁盘。

  • fsync:将文件描述符fd引用的文件修改过的元数据和数据写入磁盘。

  • fdatasync:fdatasync函数类似于fsync,但它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的属性。

手动清除Page Cache

$ sync && echo 1 > /proc/sys/vm/drop_caches

表示先执行sync命令,将所有缓存数据写入磁盘中,然后将“1”写入到/proc/sys/vm/drop_caches文件中,表示清空页缓存。

$ sync && echo 2 > /proc/sys/vm/drop_caches

表示先执行sync命令,将所有缓存数据写入磁盘中,然后将“2”写入到/proc/sys/vm/drop_caches文件中,表示清空目录缓存和页缓存。

$ sync && echo 3 > /proc/sys/vm/drop_caches

表示先执行sync命令,将所有缓存数据写入磁盘中,然后将“3”写入到/proc/sys/vm/drop_caches文件中,表示清空目录缓存、页缓存和inode缓存。

hcache工具的使用

hcache是一个用于分析和显示Page Cache统计信息的命令行工具。它可以提供关于Page Cache的详细信息,包括脏页和干净页的数量、Page Cache的大小、缓存命中率等。

hcache是基于pcstat的,pcstat可以查看某个文件是否被缓存和根据进程pid来查看都缓存了哪些文件。hcache在其基础上增加了查看整个操作系统Cache和根据使用Cache大小排序的特性。

安装:

$ wget https://silenceshell-1255345740.cos.ap-shanghai.myqcloud.com/hcache

$ chmod 755 hcache && mv hcache /usr/local/bin/

根据进程pid来查看都缓存了哪些文件

$ hcache -pid $$
+-----------------------------------------------------+----------------+------------+-----------+---------+
| Name                                                | Size (bytes)   | Pages      | Cached    | Percent |
|-----------------------------------------------------+----------------+------------+-----------+---------|
| /lib/x86_64-linux-gnu/libtinfo.so.5.9               | 170784         | 42         | 42        | 100.000 |
| /lib/x86_64-linux-gnu/ld-2.27.so                    | 179152         | 44         | 44        | 100.000 |
| /lib/x86_64-linux-gnu/libnss_compat-2.27.so         | 39744          | 10         | 10        | 100.000 |
| /lib/x86_64-linux-gnu/libnss_files-2.27.so          | 47568          | 12         | 12        | 100.000 |
| /lib/x86_64-linux-gnu/libnsl-2.27.so                | 97176          | 24         | 24        | 100.000 |
| /lib/x86_64-linux-gnu/libnss_nis-2.27.so            | 47576          | 12         | 12        | 100.000 |
| /usr/lib/locale/locale-archive                      | 3004224        | 734        | 734       | 100.000 |
| /lib/x86_64-linux-gnu/libc-2.27.so                  | 2030928        | 496        | 496       | 100.000 |
| /lib/x86_64-linux-gnu/libdl-2.27.so                 | 14560          | 4          | 4         | 100.000 |
| /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache | 26376          | 7          | 7         | 100.000 |
| /bin/bash                                           | 1113504        | 272        | 272       | 100.000 |
+-----------------------------------------------------+----------------+------------+-----------+---------+

hcache命令可以帮助您深入了解系统的Page Cache使用情况,以便进行性能分析和优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1359002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

猫咪主食冻干K9、希喂、SC生骨肉冻干哪款好?详细对比测评这三款产品

随着科学养猫的观念深入人心&#xff0c;越来越多的铲屎官开始关注猫咪主食的营养与健康。主食冻干&#xff0c;作为一种模拟猫咪原始猎食的食品&#xff0c;因其高营养保留而受到广大猫奴的喜爱。相比传统的膨化猫粮&#xff0c;主食冻干更符合猫咪的饮食天性&#xff0c;提供…

【Storm实战】1.1 图解Storm的抽象概念

文章目录 0. 前言1. Storm 中的抽象概念1.1 流 (Stream)1.2 拓扑 (Topology)1.3 Spout1.4 Bolt1.5 任务 (Task)1.6 工作者 (Worker) 2. 形象的理解Storm的抽象概念2.1 流 (Stream)2.2 拓扑 (Topology)2.3 Spout2.4 Bolt2.5 任务 (Task)2.6 工作者 (Worker)场景1场景2 3.参考文档…

如何打造家居产业数字化转型范式?林氏家居以数智供应链作答

近年来&#xff0c;我国房地产行业逐步进入深度调整期。作为下游产业&#xff0c;家居家装行业的发展也来到了新阶段。业内人士指出&#xff0c;新房市场成交规模收缩&#xff0c;家居家装企业们开始整合资源&#xff0c;向存量房市场、产品科技化以及数字化转型。 国家层面出…

教学/直播/会议触摸一体机定制_基于展锐T820安卓核心板方案

触控一体机是一种集先进的触摸屏、工控和计算机技术于一体的设备。它取代了传统的键盘鼠标输入功能&#xff0c;广泛应用于教学、培训、工业、会议、直播、高新科技展示等领域。触摸一体机的应用提升了教学、会议和展示的互动性和信息交流。 触摸一体机方案基于国产6nm旗舰芯片…

设置进程优先级

#include <windows.h>int main() {// 获取当前进程的句柄HANDLE hProcess GetCurrentProcess();// 设置当前进程的优先级为高SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);// 执行其他代码return 0; }进程优先级 标志 idle &#xff08;低&#xff09; IDL…

Python (十七) __name__ == ‘__main__‘ 作用

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

小学副科老师轻松吗

在小学里&#xff0c;除了语文、数学和英语这些主科&#xff0c;还有许多副科老师&#xff0c;他们的工作日常是什么样的呢&#xff1f;今天&#xff0c;让我们一起来揭秘小学副科老师的一天。 备课&#xff1a;在忙碌中寻找创意的火花 副科老师同样需要花费大量时间进行备课…

视频剪辑指南:如何将多个视频快速批量合并的方法

在日常生活和工作中&#xff0c;经常要将多个视频片段合并为一个完整的视频。但是手动剪辑每个视频不仅费时&#xff0c;而且效率低下。那么如何解决这个问题呢&#xff0c;可以采用一些快速批量合并视频的方法。现在一起来看看云炫AI智剪如何批量合并视频的具体步骤吧。 合并…

Windows 使用 nmap软件测试 UDP 端口

下载windows版nmap &#xff0c;下载后双机默认安装。 Download the Free Nmap Security Scanner for Linux/Mac/Windows 打开CMD &#xff0c; 输入 cd C:\Program Files (x86)\Nmap C:\Program Files (x86)\Nmap>ncat -z -v -u ntp.aliyun.com 123 Ncat: Version 7.80 ( …

《现代C++语言核心特性解析》笔记(三)

二十四、三向比较&#xff08;C20&#xff09; 1. “太空飞船”&#xff08;spaceship&#xff09;运算符 C20标准新引入了一个名为“太空飞船”&#xff08;spaceship&#xff09;的运算符 <>&#xff0c;它是一个三向比较运算符。<> 之所以被称为“太空飞船”运…

六、HTML 段落

HTML 可以将文档分割为若干段落。 一、HTML 段落 段落是通过 <p> 标签定义的。 <p>这是一个段落 </p> <p>这是另一个段落</p> 注意&#xff1a;浏览器会自动地在段落的前后添加空行。&#xff08;</p> 是块级元素&#xff09; 二、不…

篮球羽毛球乒乓球体育场馆预订小程序开发

开发一款专业的小程序&#xff0c;用于多场馆场地的预定和管理&#xff0c;包括体育馆、羽毛球馆、兵乒球馆、篮球馆等各类场馆。此小程序旨在为场馆提供全方位的运营解决方案&#xff0c;并满足会员的不同需求。 该小程序的核心功能特性包括&#xff1a; 场馆管理&#xff…

排除启动类故障----三大实验

目录 一、模拟破坏mbr和分区表然后修复 二、修复grub引导故障 三、遗忘root用户密码 一、模拟破坏mbr和分区表然后修复 1、mbr处于第一块磁盘的第一个物理扇区&#xff0c;总共512个字节&#xff0c;前446个字节是grub程序&#xff0c;后面64个字节是分区表 2、故障原因&a…

安卓平板电脑,5G通讯加持,帮你的通讯效率提提速

安卓平板电脑&#xff0c;作为一种集通讯、娱乐、工作于一体的便携设备&#xff0c;近年来随着5G通讯技术的发展&#xff0c;其在通讯效率方面迎来了新的提升。5G通讯加持&#xff0c;不仅为安卓平板电脑带来了更快速、更稳定的数据传输能力&#xff0c;也为用户的通讯效率提供…

ZigBee协议栈 -- 协议栈版本与IAR版本适配说明(Zstack2.5.1a + IAR10.30.1)

文章目录 协议栈安装工程适配 在讲到ZigBee协议栈的文章中所用的协议栈版本是Zstack2.5.1a&#xff0c;对于Zstack2.5.1a运行在IAR8.10中是可以完全适配进行编译开发的&#xff0c;现在较新版本的IAR都是10的版本以上了&#xff0c;有部分开发者习惯使用最新版本来获得更好的开…

freeRTOS的栈溢出检测机制

1、前言 后面的分析是以RISC-V架构为例&#xff0c;不同的架构在代码实现上有些许区别RISC-V架构使用的满减栈 2、任务控制块介绍&#xff08;TCB&#xff1a;task controller Block&#xff09; typedef struct tskTaskControlBlock {volatile StackType_t * pxTopOfSta…

Redis基础学习一

1. Redis 入门 1.1. Redis 诞生历程 1.1.1.从一个故事开始 08 年的时候有一个意大利西西里岛的小伙子&#xff0c;笔名 antirez&#xff08;http://invece.org/&#xff09;&#xff0c;创建了一个访客信息网站 LLOOGG.COM。有的时候我们需要知道网站的访问情况&#xff0c;…

计算化学顶刊封面!玻色量子联合上海交大张健课题组发表量子计算重要成果

​2023年12月13日&#xff0c;北京玻色量子科技有限公司&#xff08;以下简称“玻色量子”&#xff09;联合上海交通大学在中科院分区1区、计算化学领域Top刊物JCTC&#xff08;Journal of Chemical Theory and Computation&#xff09;内刊的封面上发表了以“Encoding Molecul…

两步带你解决IDEA 插件下载安装慢、超时、不成功问题

两步带你解决IDEA 插件下载安装慢、超时、不成功问题 1. 查找 国内插件的节点IP地址2. 修改本地hosts文件 > 今天在安装idea中的插件时&#xff0c;又双叒叕出现了这个问题&#xff0c;下载一个几MB的插件巨慢&#xff0c;所以写一下它的解决方案 1. 查找 国内插件的节点IP地…

中国文化文物和旅游统计年鉴,数据含pdf、excel等格式,文本形式呈现,可预览数据

基本信息. 数据名称: 中国旅游统计年鉴 数据格式: pdf、xls不定 数据时间: 2012-2020年 数据几何类型: 文本 数据坐标系: —— 数据来源&#xff1a;文化和旅游部、网络公开数据 原名为《中国旅游统计年鉴》2020年后更名为《中国文化文物和旅游统计年鉴》&#xff…