表白网站源码大全,世界工厂采购网站,搜狗提交网站入口,换友情链接的网站Page cache#xff08;页面缓存#xff09;是计算机操作系统中的一种机制#xff0c;用于将频繁访问的数据从磁盘存储到内存中#xff0c;以便更快地访问。当程序从磁盘请求数据时#xff0c;操作系统会检查该数据是否已经存在于页面缓存中。如果存在#xff0c;数据可以…Page cache页面缓存是计算机操作系统中的一种机制用于将频繁访问的数据从磁盘存储到内存中以便更快地访问。当程序从磁盘请求数据时操作系统会检查该数据是否已经存在于页面缓存中。如果存在数据可以直接从内存中获取这比从磁盘访问要快得多。如果数据不在页面缓存中它将从磁盘中获取并存储在缓存中供将来使用。
既然Page Cache是一种缓存那么缓存必然带来以下问题
占用内存多大空间内存空间满了怎么办淘汰策略内存中的数据何时写入磁盘数据如何持久化、一致性如何保障内存中的数据是否会丢失持久化的触发时机 page与Page Cache的关系
从磁盘中读取文件后写入Page Cache中是将整个文件都写入呢还是只写用到的那一部分
page是内存管理分配的基本单位Page Cache由多个page构成。page在操作系统中通常为4KB大小32bits/64bits而 Page Cache的大小则为4KB的整数倍。
操作系统为基于Page Cache的读缓存机制提供预读机制PAGE_READAHEAD例如用户线程仅仅请求读取磁盘上文件A的offset为0-3KB范围内的数据由于磁盘的基本读写单位为block4KB于是操作系统至少会读0-4KB的内容这恰好可以在一个page中装下。
但是操作系统出于局部性原理会选择将磁盘块offset[4KB,8KB)、[8KB,12KB)以及[12KB,16KB)都加载到内存于是额外在内存中申请了3个page。
下面我们用一个例子来演示一下
准备一个文本文件ooxx.txt大小为需大于4*416k
$ 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再次读到内存中。
缺页中断的作用
缺页中断是内存管理中的重要机制具有以下重要作用 页面调入内存当应用程序访问的页面不在内存中时缺页中断会触发操作系统将缺失的页面从磁盘加载到内存中。这样做的好处是不需要将整个文件或数据集一次性全部加载到内存中而是按需加载只加载应用程序实际需要的页面。这样可以节省磁盘I/O开销避免了无谓的磁盘读取操作提高了系统的性能。 页面替换策略当内存中的页面已满时如果应用程序访问一个新的页面操作系统需要选择一个页面进行替换将其换出到磁盘上为新的页面腾出空间。缺页中断提供了一个时机让操作系统可以根据页面替换算法选择合适的页面进行替换以保证内存中的页面是最有用的页面提高内存的利用率。 延迟写策略在写回策略下当应用程序对一个脏页进行写操作时脏页的写回操作不会立即进行而是推迟到后续的某个时刻进行。这样可以将多次写操作合并为一次写操作减少了磁盘写入的次数降低了磁盘I/O开销。 页面预读取为了进一步减少磁盘I/O开销操作系统可以利用缺页中断的时机进行页面预读取。当应用程序访问一个页面时操作系统可以预先加载一些相邻的页面到内存中以提前满足应用程序的访问需求。这样可以减少后续的缺页中断和磁盘读取操作提高了系统的响应速度。 权限检查和处理缺页中断还可以用于检查应用程序对页面的访问权限。操作系统可以根据页面的访问权限例如只读、读写等来判断应用程序的访问是否合法并根据需要进行相应的处理。
缺页中断的处理流程
当发生缺页中断时操作系统会按照以下步骤来处理 中断处理程序当发生缺页中断时CPU会暂停当前应用程序的执行并跳转到操作系统的中断处理程序。这个中断处理程序负责处理缺页中断。 中断处理程序的执行中断处理程序会首先保存当前应用程序的上下文信息包括寄存器的值和程序计数器等。然后它会根据缺页中断的原因进行相应的处理。 页面调入内存如果缺页中断是由于应用程序访问的页面不在内存中引起的操作系统会触发页面调入内存的过程。它会根据页面表中的信息确定需要调入的页面的位置和大小并从磁盘上读取相应的页面数据。 磁盘I/O操作在页面调入内存的过程中操作系统会进行磁盘I/O操作将需要的页面数据从磁盘读取到内存中。这包括了磁盘寻道、读取数据和数据传输等操作。 更新页表当页面数据成功加载到内存中后操作系统会更新页表将该页面的状态设置为已加载并将页面的物理地址映射到对应的虚拟地址。 恢复上下文和重新执行应用程序当页面调入内存完成后中断处理程序会恢复之前保存的应用程序的上下文信息并将控制权返回给应用程序。应用程序会继续执行之前被中断的指令但这次访问的页面已经在内存中了不会再触发缺页中断。
Page Cache的工作原理
Page Cache的工作原理如下 当应用程序打开一个文件并读取其中的数据时操作系统会将文件的内容读取到内存中并将其缓存为一个或多个页通常是4KB大小的页。 这些缓存的页被存储在一个被称为Page Cache的内存区域中它是内核管理的一部分。 当应用程序再次访问相同的文件时操作系统首先检查Page Cache中是否存在这些页的副本。如果存在操作系统会直接从Page Cache中返回数据而不需要再次访问磁盘。 如果应用程序对文件进行写操作数据会被写入到Page Cache中的脏页dirty page。脏页表示该页的内容已经被修改但还没有写回到磁盘。 当系统内存压力较大或需要释放内存时内核会触发缓存刷新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_modeS_IFREG|0664, st_size0, ...}) 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该参数指定了脏数据在内存中能够存活的时间单位为百分之一秒。当脏数据在内存中超过这个时间后系统会将其异步写入磁盘中默认值为300030秒。 vm.dirty_writeback_centisecs表示系统在多长时间内进行一次脏数据的后台写回操作。它的单位是百分之一秒centiseconds默认值为500即系统每5秒钟进行一次后台写回操作。 vm.dirtytime_expire_seconds代表内存中脏数据的允许存储时间单位为秒。当脏数据在内存中存储的时间超过这个时间系统会将其写入磁盘以释放内存。
跟pagecache相关的系统调用
内核提供了下面这些把Page Cache中内容写入磁盘的系统调用 sync将所有未写的系统缓冲区数据写入磁盘不需要带任何参数。 syncfssyncfs需要一个文件描述符只将文件描述符指向的文件相关的文件系统的缓冲区数据写入磁盘。 fsync将文件描述符fd引用的文件修改过的元数据和数据写入磁盘。 fdatasyncfdatasync函数类似于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使用情况以便进行性能分析和优化。