页面缓冲(Page Cache)的管理

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

一、本文分析文件的读写过程。当用户进程发出一个read()系统调用时,它首先通过VFS从disk cache中去查找相应的文件块有没有已经被缓存起来,如果有,则不需要再次从设备中去读,直接从CACHE中去拷贝给用户缓冲区就可以了,否则它就要先分配一个缓冲页面,并且将其加入到对应的inode节点的address_space中,再调用address_space的readpage()函数,通过submit_bio()向设备发送一个请求,将所需的文件块从设备中读取出来存放在先前分配的缓冲页面中,最后再从该页面中将所需数据拷贝到用户缓冲区。

图1

二、页面缓冲(Page Cache)的管理

页面缓冲的核心数据结构是struct address_space :

struct backing_dev_info;

struct address_space {

       struct inode           *host;            /* owner: inode, block_device */

       struct radix_tree_root    page_tree;       /* radix tree of all pages */

       rwlock_t        tree_lock;       /* and rwlock protecting it */

       unsigned int           i_mmap_writable;/* count VM_SHARED mappings */

       struct prio_tree_root      i_mmap;         /* tree of private and shared mappings */

       struct list_head       i_mmap_nonlinear;/*list VM_NONLINEAR mappings */

       spinlock_t              i_mmap_lock; /* protect tree, count, list */

       unsigned int           truncate_count;      /* Cover race condition with truncate */

       unsigned long         nrpages; /* number of total pages */

       pgoff_t                  writeback_index;/* writeback starts here */

       const struct address_space_operations *a_ops;   /* methods */

       unsigned long         flags;             /* error bits/gfp mask */

       struct backing_dev_info *backing_dev_info; /* device readahead, etc */

       spinlock_t              private_lock;   /* for use by the address_space */

       struct list_head       private_list;     /* ditto */

       struct address_space     *assoc_mapping;    /* ditto */

} __attribute__((aligned(sizeof(long))));

如下图2,缓冲页面的是通过一个基数树(Radix Tree)来管理的,这是一个简单但非常高效的树结构。

图2

由图2可以看到,当RADIX_TREE_MAP_SHIFT为6(即每个节点有2^6=64个slot)且树高是1时,它可以寻址大小为64个页面(256kb)的文件,同样,当树高为2时,它可以寻址64*64个页面(16M)大小的文件,如此下去,在32位的系统中,树高为6级,(最高级只有2位:32-6*5),所以它可以寻址2^32-1个页面大小的文件,约为16TB大小,所以目前来说已经足够了。

基数树的遍历也是很简单,且类似于虚拟线性地址的转换过程。只要给定树根及文件偏移,就可以找到相应的缓存页面。再如图2右,如果在文件中的偏移为131个页面,这个偏移值的高6位就是第一级偏移,而低6位就是在第二级的偏移,依此类推。如对于偏移值131(10000011),高6位值是131>>6 = 2,所以它在第一级的偏移是2,而在第2级的领衔就是低6位,值为3,即偏移为3,所以得到的结果如图2右方所示。

#define RADIX_TREE_MAP_SHIFT   (CONFIG_BASE_SMALL ? 4 : 6)

#define RADIX_TREE_MAP_SIZE      (1UL << RADIX_TREE_MAP_SHIFT)

#define RADIX_TREE_MAX_TAGS 2

#define RADIX_TREE_TAG_LONGS /    //其值为64

       ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG)

struct radix_tree_node {

       unsigned int    height;            /* Height from the bottom */

       unsigned int    count;

       struct rcu_head      rcu_head;

       void        *slots[RADIX_TREE_MAP_SIZE];

       unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];

};

struct radix_tree_path {

       struct radix_tree_node *node;

       int offset;

};

以上是相关的几个数据结构,第一个为树的结点结构,第二个用于路径查找。

注意节点结构中的tags域,这个一个典型的用空间换时间的应用。它是一个二维数组,用于记录该节点下面的子节点有没有相应的标志。目前RADIX_TREE_MAX_TAGS为2,表示只记录两个标志,其中tags[0]为PAGE_CACHE_DIRTY,tags[1]为PAGE_CACHE_WRITEBACK。它表示,如果当前节点的tags[0]值为1,那么它的子树节点就存在PAGE_CACHE_DIRTY节点,否则这个子树分枝就不存在着这样的节点,就不必再查找这个子树了。比如在查找PG_dirty的页面时,就不需要遍历整个树,而可以跳过那些tags[0]为0值的子树,这样就提高了查找效率。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/74194/showart_1089736.html

北航操作系统课程核心知识点实战解析:从课堂测试看操作系统设计精髓 本文深入解析北航操作系统课程的核心知识点,通过课堂测试题目揭示操作系统设计的精髓。从进程同步、内存管理到文件系统设计,结合实际代码示例和工程实践,帮助读者掌握操作系统底层原理和实战技巧,提升解决复杂系统问题的能力。 阅读详情

相关推荐

page cache和buffer cache之间的关系以及验证

Linux系统存在两种缓存机制,分别是Page Cache和Buffer Cache, 其中Page Cache缓存文件的以优化文件IO。Buffer Cache缓存块设备的块以优化块设备IO。

tugouxp的专栏 2340

操作系统复习——虚存管理

上一次复习我们讲到实存管理,就是把内容放到运行内存里面。目前我们用的手机,大部分运行内存是6GB、8GB、12GB等。但是目前随着科技的进步,视频像素也不断升高,有时候,我们一个视频就是十几GB,如果只有实存管理的话,那么我们一下子就要把整个视频放进去,这个时候就会导致卡顿,所以我们需要采用其它的技术——虚存管理。① 表② 地址变换机构 PMT (P,d)(Fnum, d)③ 性能评价 有效访问时间 碎片情况① 表需要有哪些内容?② PMT 所需页面不在内存? 分配给该进程的框都装有页面

m0_53244895的博客 2623

[内核内存] page cache

文章目录page cache 和 buffer cachepage cachepage cache的文件读写基本流程()读文件写文件小结 page cache 和 buffer cache linux在I/O的过程中,磁盘读写数据的速度远远低于内存读写数据的速度。因此为了加快内存处理磁盘数据的速度,linux将从磁盘中读取的数据缓存到内存的某一空闲区域。这些缓存磁盘数据的内存区域被称为缓冲区。 在linux不支持虚拟内存机制前linux不存在的概念,内存读取磁盘数据以设备块为单位,因而linux I/

菁的博客 2937

系统缺率与缓冲队列

系统缺率是指在一段时间内,操作系统因缺而产生的失效次数占总内存访问次数的比例。它衡量了虚拟内存管理系统的效率,缺率越低,表示内存管理系统效率越高,程序运行速度越快。

weixin_49342084的博客 2664

操作系统 第三章 3.2 错题整理

B 进程之间从运行态进入阻塞态 cpu检测到后 调度其他进程上处理机运行 不是因为系统调用。缓冲队列是内存和外存之间的 缺队列越长 在队列中找到该页面的几率越大。虚拟存储器包括内存和磁盘对换区,工作集要频繁用到,应该放在主存。一个页面能存放2^9个表项 号9bit,36/9=4。才置换 和系统调用无关。合法位=存在位 不存在即发生故障。区分好表项和逻辑地址 是不同的。C fork系统调用创建新进程。缺率是CPU和内存之间的。页面引用串长度是什么意思。工作集和驻留集有点混淆。

weixin_46716100的博客 1532

什么是缓存(Page Cache)(转载)

我们知道文件一般存放在硬盘(机械硬盘或固态硬盘)中,CPU 并不能直接访问硬盘中的数据,而是需要先将硬盘中的数据读入到内存中,然后才能被 CPU 访问。 由于读写硬盘的速度比读写内存要慢很多(DDR4 内存读写速度是机械硬盘500倍,是固态硬盘的200倍),所以为了避免每次读写文件时,都需要对硬盘进行读写操作,Linux 内核使用缓存(Page Cache)机制来对文件中的数据进行缓存。 本文使用的 Linux 内核版本为:Linux-2.6.23 什么是缓存 为了提升对文件的读写效率,Li

一个嵌入式软件工程师的博客 8528

缓冲队列 BlockingQueue

文章预览:缓冲队列 BlockingQueue一、BlockingQueue缓存队列简单概述1、什么是阻塞队列BlockingQueue2、BlockingQueue接口中的部分方法3、BlockingQueue的父类与部分实现类二、ArrayBlockingQueue类1、什么是ArrayBlockingQueue2、ArrayBlockingQueue中的四组API3、代码实现三、SynchronousQueue类1、什么是SynchronousQueue(同步队列)2、使用代码去解释上述的内容 缓冲

weixin_43512946的博客 1921

文件读写(1)--页面缓冲(Page Cache)管理

文件读写(1)--页面缓冲(Page Cache)管理R.wen 一、本文分析文件的读写过程。当用户进程发出一个read()系统调用时,它首先通过VFS从disk cache中去查找相应的文件块有没有已经被缓存起来,如果有,则不需要再次从设备中去读,直接从CACHE中去拷贝给用户缓冲区就可以了,否则它就要先分配一个缓冲页面

thewayma的专栏 998

Linux IO的buffer cachepage cache的区别,以及二者合并的原因

What is the major difference between the buffer cache and the page cache? Why were they separate entities in older kernels? Why were they merged later on? 原文地址:quora.com/Linux-Kernel The page cache ...

去级得骨灰 1273

linux的高速缓存增加,LINUX使用的缓存,缓冲区高速缓存

6.7.2缓冲区高速缓存Linux采用了缓冲区高速缓存机制,而不同于其他操作系统的“写透”方式,也就是说,当你把一个数据写入文件时,内核将把数据写入内存缓冲区,而不是直接写入磁盘。在这里要用到一个数据结构 buffer_head它是用来描述缓冲区的数据结构缓冲区的大小一般要比页面尺寸小,所以一页面中可以包含数个缓冲区,同一页面中的缓冲区用链表连接。回忆页面结构page,其中有一个域buffer_...

weixin_39671374的博客 348

虚拟内存

--from davidlee (他应该是转载的) 虚拟内存为一个比物理内存大许多倍的虚拟出来的内存,它做为文件被保存在硬盘上。每个进程拥有自己的表,表的存在是为了把虚拟内存地址转换为物理内存地址,因为对于进程来说,它看到...

congchenjin2969的博客 115

blkdev_write_iter

这篇文章分析了Linux内核中块设备写入操作的实现过程。主要涉及blkdev_write_iter函数的调用链,该函数处理块设备的数据写入请求,经过多层调用最终完成数据写入。关键步骤包括:1)权限和空间检查;2)通过__generic_file_write_iter处理通用文件写入逻辑;3)使用generic_perform_write执行具体写入操作;4)通过block_write_begin准备写入环境并分配页面缓存。整个过程涉及地址空间操作、页面缓存管理、块设备驱动交互等多个内核子系统,展示了Linu

wmzjzwlzs的专栏 420

linux那些事之page cache

page cache page cache又称高速缓存,主要是针对文件文件系统,为了减少不必要的磁盘IO操作(读/写)造成卡顿问题,内核将磁盘文件中的内容缓存到内存中,并选择适当时机对磁盘进行读写操作。 page cache在linux文件系统中占用重要地位。主要是由于CPU访问磁盘比从内存中读取要慢上百甚至上千倍;同时利用空间和时间局部性,当系统访问该文件中一定位置的内容之后,那么经常会很快访问附近位置,如果能提前将文件一部分内容缓存到内存中将会加快对文件操作效率。 he Linux kernel

weixin_42730667的博客 2412

浅谈linux内核中内存分配函数

linux内核为了高效的管理内存,提供了很多内存申请的函数。在不同的情况下要使用不同的内存分配函数,下面我们根据具体情况来分析看下。 1) void *kmem_cache_alloc(kmem_cache_t *cachep, int flags); void *kmem_cache_free(kmem cache_t *cachep, void *obj...

weixin_30716725的博客 134

Kafka【五】Buffer Cache (缓冲区缓存)Page Cache (缓存)和零拷贝技术

传统的主要用于缓存块设备上的数据块,包括文件系统的元数据和数据本身。它的主要目的是提高对块设备的读写性能,减少磁盘I/O操作,从而提升系统整体性能。尽管作为一个单独的概念在较新的Linux内核版本中已经不再单独存在,但它所代表的缓存机制仍然是提高系统性能的重要手段之一。通过缓存块设备上的数据和元数据,能够显著减少磁盘I/O操作,提高文件系统的读写性能。在现代Linux内核中,这种缓存机制已经被整合到统一的缓存机制中,以更好地适应现代计算环境的需求。缓存的对象Page cache:主要用于缓存文件的内容。

小小默:进无止境 3112

Page Cache

Page Cache是 Linux 内存中的一部分,用来缓存从磁盘读取的文件数据,或者待写入磁盘的数据。它以“Page)”为单位管理,一般是 4KB 大小。属于 Linux 的统一缓冲高速缓存系统(Unified Buffer Cache)。特性描述是什么用于缓存文件内容的内存优点加快读写,减少磁盘压力缓存方式自动管理、基于(通常4KB)清理方式可通过手动清理查看free -hvmstat -m想看某个具体进程或容器用了多少 Page Cache,也可以进一步用smem。

喝醉酒的小白 1017

Linux系统中的Page cache和Buffer cache

Free命令显示内存 首先,我们来了解下内存的使用情况: Mem:表示物理内存统计 total:表示物理内存总量(total = used + free) used:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。 free:未被分配的内存。 shared:共享内存。 buffers:系统分配但未被使用的buffers 数量。 cached:系统分配但未被使用的cache 数量。 -/+ buffers/cache:表示物理内存.

【欢迎关注公众号:冬瓜白】 563

page cache

Linux PageCache机制解析:XArray与RadixTree的演进 摘要:PageCache是Linux文件IO的核心机制,通过物理缓存加速文件读写。传统RadixTree索引存在并发性能差、标记维护复杂等问题,Linux 5.x后全面采用XArray作为PageCache索引。XArray具备三大优势:1)稀疏存储节省内存;2)内置DIRTY/WRITEBACK等标记系统,快速定位脏;3)RCU无锁读机制实现高并发。相比RadixTree,XArray专为PageCache优化,提供更简单

tangzhangyin的专栏 463

block(),page(),buffer cache(块缓冲)区别与联系

在自己的理解里,块就是用来管理磁盘空间的,就像我们在给一个磁盘建立

dymom的专栏 1万+
下一篇: 关于Linux的Cron进程的学习总结
killerxp
博客等级 码龄22年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值