`
netcome
  • 浏览: 479933 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Linux 内核的文件 Cache 管理机制介绍

阅读更多

1 前言

自从诞生以来,Linux 就被不断完善和普及,目前它已经成为主流通用操作系统之一,使用得非常广泛,它与 Windows、UNIX 一起占据了操作系统领域几乎所有的市场份额。特别是在高性能计算领域,Linux 已经成为一个占主导地位的操作系统,在2005年6月全球TOP500 计算机中,有 301 台部署的是 Linux 操作系统。因此,研究和使用 Linux 已经成为开发者的不可回避的问题了。

下面我们介绍一下 Linux 内核中文件 Cache 管理的机制。本文以 2.6 系列内核为基准,主要讲述工作原理、数据结构和算法,不涉及具体代码。





回页首


2 操作系统和文件 Cache 管理

操作系统是计算机上最重要的系统软件,它负责管理各种物理资源,并向应用程序提供各种抽象接口以便其使用这些物理资源。从应用程序的角度看,操作系统提供了一个统一的虚拟机,在该虚拟机中没有各种机器的具体细节,只有进程、文件、地址空间以及进程间通信等逻辑概念。这种抽象虚拟机使得应用程序的开发变得相对容易:开发者只需与虚拟机中的各种逻辑对象交互,而不需要了解各种机器的具体细节。此外,这些抽象的逻辑对象使得操作系统能够很容易隔离并保护各个应用程序。

对于存储设备上的数据,操作系统向应用程序提供的逻辑概念就是"文件"。应用程序要存储或访问数据时,只需读或者写"文件"的一维地址空间即可,而这个地址空间与存储设备上存储块之间的对应关系则由操作系统维护。

在 Linux 操作系统中,当应用程序需要读取文件中的数据时,操作系统先分配一些内存,将数据从存储设备读入到这些内存中,然后再将数据分发给应用程序;当需要往文件中写数据时,操作系统先分配内存接收用户数据,然后再将数据从内存写到磁盘上。文件 Cache 管理指的就是对这些由操作系统分配,并用来存储文件数据的内存的管理。 Cache 管理的优劣通过两个指标衡量:一是 Cache 命中率,Cache 命中时数据可以直接从内存中获取,不再需要访问低速外设,因而可以显著提高性能;二是有效 Cache 的比率,有效 Cache 是指真正会被访问到的 Cache 项,如果有效 Cache 的比率偏低,则相当部分磁盘带宽会被浪费到读取无用 Cache 上,而且无用 Cache 会间接导致系统内存紧张,最后可能会严重影响性能。

下面分别介绍文件 Cache 管理在 Linux 操作系统中的地位和作用、Linux 中文件 Cache相关的数据结构、Linux 中文件 Cache 的预读和替换、Linux 中文件 Cache 相关 API 及其实现。





回页首


2 文件 Cache 的地位和作用

文件 Cache 是文件数据在内存中的副本,因此文件 Cache 管理与内存管理系统和文件系统都相关:一方面文件 Cache 作为物理内存的一部分,需要参与物理内存的分配回收过程,另一方面文件 Cache 中的数据来源于存储设备上的文件,需要通过文件系统与存储设备进行读写交互。从操作系统的角度考虑,文件 Cache 可以看做是内存管理系统与文件系统之间的联系纽带。因此,文件 Cache 管理是操作系统的一个重要组成部分,它的性能直接影响着文件系统和内存管理系统的性能。

图1描述了 Linux 操作系统中文件 Cache 管理与内存管理以及文件系统的关系示意图。从图中可以看到,在 Linux 中,具体文件系统,如 ext2/ext3、jfs、ntfs 等,负责在文件 Cache和存储设备之间交换数据,位于具体文件系统之上的虚拟文件系统VFS负责在应用程序和文件 Cache 之间通过 read/write 等接口交换数据,而内存管理系统负责文件 Cache 的分配和回收,同时虚拟内存管理系统(VMM)则允许应用程序和文件 Cache 之间通过 memory map的方式交换数据。可见,在 Linux 系统中,文件 Cache 是内存管理系统、文件系统以及应用程序之间的一个联系枢纽。


 




回页首


3 文件 Cache 相关数据结构

在 Linux 的实现中,文件 Cache 分为两个层面,一是 Page Cache,另一个 Buffer Cache,每一个 Page Cache 包含若干 Buffer Cache。内存管理系统和 VFS 只与 Page Cache 交互,内存管理系统负责维护每项 Page Cache 的分配和回收,同时在使用 memory map 方式访问时负责建立映射;VFS 负责 Page Cache 与用户空间的数据交换。而具体文件系统则一般只与 Buffer Cache 交互,它们负责在外围存储设备和 Buffer Cache 之间交换数据。Page Cache、Buffer Cache、文件以及磁盘之间的关系如图 2 所示,Page 结构和 buffer_head 数据结构的关系如图 3 所示。在上述两个图中,假定了 Page 的大小是 4K,磁盘块的大小是 1K。本文所讲述的,主要是指对 Page Cache 的管理。

在 Linux 内核中,文件的每个数据块最多只能对应一个 Page Cache 项,它通过两个数据结构来管理这些 Cache 项,一个是 radix tree,另一个是双向链表。Radix tree 是一种搜索树,Linux 内核利用这个数据结构来通过文件内偏移快速定位 Cache 项,图 4 是 radix tree的一个示意图,该 radix tree 的分叉为4(22),树高为4,用来快速定位8位文件内偏移。Linux(2.6.7) 内核中的分叉为 64(26),树高为 6(64位系统)或者 11(32位系统),用来快速定位 32 位或者 64 位偏移,radix tree 中的每一个叶子节点指向文件内相应偏移所对应的Cache项。

另一个数据结构是双向链表,Linux内核为每一片物理内存区域(zone)维护active_list和inactive_list两个双向链表,这两个list主要用来实现物理内存的回收。这两个链表上除了文件Cache之外,还包括其它匿名(Anonymous)内存,如进程堆栈等。


 

 

 




回页首


4 文件Cache的预读和替换

Linux内核中文件预读算法的具体过程是这样的:对于每个文件的第一个读请求,系统读入所请求的页面并读入紧随其后的少数几个页面(不少于一个页面,通常是三个页面),这时的预读称为同步预读。对于第二次读请求,如果所读页面不在Cache中,即不在前次预读的group中,则表明文件访问不是顺序访问,系统继续采用同步预读;如果所读页面在Cache中,则表明前次预读命中,操作系统把预读group扩大一倍,并让底层文件系统读入group中剩下尚不在Cache中的文件数据块,这时的预读称为异步预读。无论第二次读请求是否命中,系统都要更新当前预读group的大小。此外,系统中定义了一个window,它包括前一次预读的group和本次预读的group。任何接下来的读请求都会处于两种情况之一:第一种情况是所请求的页面处于预读window中,这时继续进行异步预读并更新相应的window和group;第二种情况是所请求的页面处于预读window之外,这时系统就要进行同步预读并重置相应的window和group。图5是Linux内核预读机制的一个示意图,其中a是某次读操作之前的情况,b是读操作所请求页面不在window中的情况,而c是读操作所请求页面在window中的情况。

Linux内核中文件Cache替换的具体过程是这样的:刚刚分配的Cache项链入到inactive_list头部,并将其状态设置为active,当内存不够需要回收Cache时,系统首先从尾部开始反向扫描active_list并将状态不是referenced的项链入到inactive_list的头部,然后系统反向扫描inactive_list,如果所扫描的项的处于合适的状态就回收该项,直到回收了足够数目的Cache项。Cache替换算法如图6的算法描述伪码所示。


 


图6 Linux的Cache替换算法描述
Mark_Accessed(b) {
       if b.state==(UNACTIVE && UNREFERENCE) 
	      							b.state = REFERENCE
       						 else if b.state == (UNACTIVE && REFERENCE) {
	      							b.state = (ACTIVE && UNREFERENCE)
	      					        Add X to tail of active_list
       						 } else if b.state == (ACTIVE && UNREFERENCE) 
	      							b.state = (ACTIVE && REFERENCE)
}
Reclaim() {
       						 if active_list not empty and scan_num<MAX_SCAN1
							 {
	      							X = head of active_list
              						if (X.state & REFERENCE) == 0
                    					Add X to tail of inactive_list
              						else {
										X.state &=  ~REFERENCE
Move X to tail of active_list
                                    }
              						scan_num++
       						 }
       						 scan_num = 0
       						 if inactive_list not emptry and scan_num <
							 MAX_SCAN2 {
              						X = head of inactive_list 
              						if (X.state & REFERENCE) == 0
                  						return X
              						else {
									X.state = ACTIVE | UNREFERENCE
Move X to tail of active_list
                                    }
              						scan_num++
       						 }
       						 return NULL
}
Access(b){
       						 if b is not in cache {
	      							if slot X free
		    							put b into X
	      							else {
		    							X=Reclaim()
		    							put b into X
              						}
	      							Add X to tail of inactive_list
       						 }
       						 Mark_Accessed(X)
}





回页首


5 文件Cache相关API及其实现

Linux内核中与文件Cache操作相关的API有很多,按其使用方式可以分成两类:一类是以拷贝方式操作的相关接口, 如read/write/sendfile等,其中sendfile在2.6系列的内核中已经不再支持;另一类是以地址映射方式操作的相关接口,如mmap等。

第一种类型的API在不同文件的Cache之间或者Cache与应用程序所提供的用户空间buffer之间拷贝数据,其实现原理如图7所示。


 

第二种类型的API将Cache项映射到用户空间,使得应用程序可以像使用内存指针一样访问文件,Memory map访问Cache的方式在内核中是采用请求页面机制实现的,其工作过程如图8所示。


 

首先,应用程序调用mmap(图中1),陷入到内核中后调用do_mmap_pgoff(图中2)。该函数从应用程序的地址空间中分配一段区域作为映射的内存地址,并使用一个VMA(vm_area_struct)结构代表该区域,之后就返回到应用程序(图中3)。当应用程序访问mmap所返回的地址指针时(图中4),由于虚实映射尚未建立,会触发缺页中断(图中5)。之后系统会调用缺页中断处理函数(图中6),在缺页中断处理函数中,内核通过相应区域的VMA结构判断出该区域属于文件映射,于是调用具体文件系统的接口读入相应的Page Cache项(图中7、8、9),并填写相应的虚实映射表。经过这些步骤之后,应用程序就可以正常访问相应的内存区域了。





回页首


6 小结

文件Cache管理是Linux操作系统的一个重要组成部分,同时也是研究领域一个很热门的研究方向。目前,Linux内核在这个方面的工作集中在开发更有效的Cache替换算法上,如LIRS(其变种ClockPro)、ARC等。相关信息可见http://linux-mm.org/AdvancedPageReplacement

分享到:
评论

相关推荐

    Linux系统内核文件Cache管理机制

    Linux系统内核的文件Cache管理机制是其高效运行的关键组件之一,尤其是在高性能计算场景中,Linux的主导地位离不开对文件I/O的优化。文件Cache管理的主要目标是提高数据访问速度和减少磁盘I/O,从而提升整体系统性能...

    Linux内核内存Cache机制原理

    1. **Page Cache**:这是Linux内核用于缓存文件内容的机制。当一个文件被打开并读取时,其内容会被复制到内存的Page Cache中。这样,后续对同一文件的访问就可以直接从内存中获取数据,而无需等待较慢的磁盘操作。...

    linux 内核 cache 管理介绍

    页缓存是Linux内核中最主要的缓存机制,用于存储文件系统的数据页。当应用程序请求读取文件时,内核首先检查页缓存中是否存在所需的数据,如果存在,就直接从缓存中读取,避免了慢速的磁盘I/O。同时,写操作也会优先...

    编程技术_Linux 内核文件Cache_机制-综合文档

    在Linux操作系统中,内核文件缓存(File Cache...总之,Linux内核文件Cache机制在提升系统性能方面起着至关重要的作用,通过理解其工作原理和优化策略,我们可以更好地利用这一功能,为各种应用场景提供更高效的服务。

    介绍linux cache机制

    Linux系统中的Cache机制主要是为了提高文件读写的效率而设计的。在Linux中,Cache主要以页面Cache...而理解Linux内核的Cache机制和相关函数,对于深入理解Linux内核的文件系统、内存管理以及提高系统性能都有重要意义。

    linux内核2.6cache源代码

    Linux内核2.6版本中的缓存(Cache)机制是操作系统设计的重要组成部分,它极大地提升了系统性能,尤其是在处理大量数据时。在这个版本的内核中,缓存的设计和实现已经相当成熟,涉及到内存管理、I/O操作、进程调度等...

    linux内核系统文件详解

    Linux 内核系统文件是 Linux 操作系统的核心组件之一,负责管理系统的硬件资源、进程调度、内存管理、网络通信等多方面的功能。在 Linux 系统中,有许多重要的系统文件,掌握这些文件的作用和用途对于 Linux 系统的...

    Linux内核缓冲区管理

    在Linux系统中,缓冲区管理机制确保了内存资源的有效利用,尤其是在处理I/O操作时,如磁盘读写,网络传输等。本文将深入探讨Linux内核缓冲区管理的原理、设计和实现,以及它对系统性能的影响。 首先,理解缓冲区...

    linux内核缓冲区管理课件.rar

    4. **页面缓存(Page Cache)**:Linux内核使用页面缓存来存储文件系统的数据。它将磁盘上的文件以完整的页为单位缓存到内存中,从而提高了读写速度。 5. **脏页(Dirty Pages)**:当内存中的缓冲区内容被修改但还...

    Linux内核(中文版)

    Linux内核通过内存管理机制来高效地分配和回收内存资源,包括虚拟内存、物理内存的管理。 **1.3 总线** 总线是计算机内部各组件之间通信的通道。Linux内核通过总线驱动和控制器驱动来管理和优化设备之间的数据传输...

    LINUX内核经典面试题

    1. Linux内核锁:Linux内核中主要有自旋锁和信号量两种锁机制。自旋锁用于保护短暂的、不会引起阻塞的临界区,而信号量则允许任务在无法获取锁时进入睡眠状态,适合处理可能长时间持有锁的情况。 2. 用户模式与内核...

    linux内核缓冲区管理

    本文将详细介绍Linux内核中的缓冲区管理机制,特别是Slab分配算法的原理与应用。 #### 二、Linux内核中的内存分配算法 Linux内核提供了多种内存分配算法来满足不同场景下的需求,主要包括: 1. **Power of Two** ...

    Linux内核情景分析

    Linux内核是操作系统的核心部分,负责管理系统的硬件资源,提供基础服务给上层的应用程序,以及维护系统的稳定性与安全性。本篇文章将深入探讨Linux内核的一些关键知识点,以帮助读者理解其工作原理和应用场景。 ...

    Linux内核内存管理技术分享

    Linux内核内存管理技术是一个复杂的系统,涉及到计算机体系结构、MMU、Cache、DMA、EPT、虚拟地址空间布局、伙伴系统、SLAB、用户空间地址布局、匿名页和文件页、缺页异常、反向映射、内存规整、OOM、KSM、巨型页、...

    Linux内核分析与应用课件第4章(一)内存管理机制.pdf

    Linux内核分析与应用课件第4章(一)内存管理机制 Linux内核分析与应用课件的第四章主要讲解了Linux内存管理机制。Linux内存管理机制包括虚拟内存实现机制、物理内存管理、进程虚拟地址空间管理、内存分配和回收...

    Linux内核编程指南第3版.zip

    1. **Linux内核基础**:介绍Linux内核的基本架构,如进程管理、内存管理、调度算法等,帮助读者理解Linux操作系统的核心运作机制。 2. **内核模块编程**:讲解如何编写和加载内核模块,这是进行内核编程的基础。...

    上海交大Linux内核作业源代码

    内存管理是Linux内核中的关键组件,负责分配和释放内存、页面交换以及内存分页等。学生将学习如何使用`kmalloc`和`kfree`进行内核空间的动态内存分配,理解物理内存和虚拟内存的区别,以及页表、页框管理器(例如...

Global site tag (gtag.js) - Google Analytics