logo资料库

介绍linux cache机制.pdf

第1页 / 共31页
第2页 / 共31页
第3页 / 共31页
第4页 / 共31页
第5页 / 共31页
第6页 / 共31页
第7页 / 共31页
第8页 / 共31页
资料共31页,剩余部分请下载后查看
Linux 内核文件 Cache 机制   Linux内核文件Cache 机制  http://www.ilinuxkernel.com    本文链接: http://ilinuxkernel.com/?p=1700  1     
Linux 内核文件 Cache 机制  目 录Table of Contents 1  概述 ........................................................................................................................... 5  2  Cache重要数据结构和函数 ........................................................................................ 7  2.1  address_space .................................................................................................... 7  address_space_operations................................................................................ 10  2.2  find_get_page() ............................................................................................. 11  2.3  2.4  add_to_page_cache() ................................................................................... 12  2.5  remove_from_page_cache() ......................................................................... 13  3  Linux内核预读机制 .................................................................................................. 14  3.1  file_ra_state数据结构 ......................................................................................... 15  do_generic_file_read() .................................................................................. 16  3.2  page_cache_sync_readahead() ................................................................... 17  3.3  3.4  page_cache_async_readahead() ................................................................. 18  ondemand_readahead() ............................................................................... 19  3.5  ra_submit() .................................................................................................... 22  3.6  3.7  __do_page_cache_readahead() ................................................................... 22  3.8  read_pages() ................................................................................................ 24  3.9  mpage_readpages() ..................................................................................... 25  4  文件读写I/O流程与Cache机制 ................................................................................. 26  4.1  读文件过程 ......................................................................................................... 26  4.1.1  数据不在页面Cache中 ................................................................................. 27  4.1.2  数据在页面Cache中 ..................................................................................... 28  4.2  写文件过程 ......................................................................................................... 29  2     
Linux 内核文件 Cache 机制  图目录 List of Figures 图1 内核中块设备操作流程 ......................................................................................................... 6  3     
Linux 内核文件 Cache 机制  表目录 List of Tables 表1 address_space对象成员变量含义 ......................................................................................... 8  表2 file_ra_state数据结构成员变量含义 ..................................................................................... 16  4       
Linux 内核文件 Cache 机制    1 概述 在我们使用Linux时,使用free命令观察系统内存使用情况,如下面空间内存为 66053100k。可能很多人都遇到过一个问题,发现随着时间的推移,内存的free越来越小, 而cached越来越大;于是就以为是不是自己的程序存在内存泄漏,或者是硬件、操作系统 出了问题?显然,从这里看不出用户程序是否有内存泄漏,也不是内核有Bug或硬件有问题。 原因是内核的文件Cache机制。实际上文件Cache的实现是页面Cache,本文后续都以页面 Cache来描述。 [root@localhost ~]# free total used free shared buffers cached Mem: 66053100 1727572 64325528 0 242492 409440 -/+ buffers/cache: 1075640 64977460 Swap: 2097144 0 2097144 当应用程序需要读取文件中的数据时,操作系统先分配一些内存,将数据从存储设备读 入到这些内存中,然后再将数据分发给应用程序;当需要往文件中写数据时,操作系统先分 配内存接收用户数据,然后再将数据从内存写到磁盘上。文件Cache管理指的就是对这些由 操作系统内核分配,并用来存储文件数据的内存管理。 在大部分情况下,内核在读写磁盘时都先通过页面Cache。若页面不在Cache中,新页 加入到页面Cache中,并用从磁盘上读来的数据来填充页面。如果内存有足够的内存空间, 该页可以在页面Cache长时间驻留,其他进程再访问该部分数据时,不需要访问磁盘。这就 是free命令显示内核free值越来越小,cached值越来越大的原因。 同样,在把一页数据写到块设备之前,内核首先检查对应的页是否已经在页面Cache 中;如果不在,就在页面Cache增加一个新页面,并用要写到磁盘的数据来填充。数据的I/O 传输并不会立即开始执行,而是会延迟几秒左右;这样进程就有机会进一步修改写到磁盘的 数据。 内核的代码和数据结构不必从磁盘读,也不必写入磁盘。因此页面Cache可能是下面的 类型:  含有普通文件数据的页;   5 
   含有目录的页; Linux 内核文件 Cache 机制   含有直接从块设备文件(跳过文件系统层)读出的数据页;  含有用户态进程数据的页,但页中的数据已被交换到磁盘;  属于特殊文件系统的页,如进程间通信中的特殊文件系统shm。 图1是块设备I/O操作流程图,从图中我们可以看出具体文件系统(如ext3/ext4、xfs等), 负责在文件Cache和存储设备之间交换数据,位于具体文件系统之上的虚拟文件系统VFS负 责在应用程序和文件 Cache 之间通过read()/write()等接口交换数据。 Virtual Filesystem (VFS) Layer Buffer Cache (Page Direct IO Disk Filesystem Disk Filesystem Generic Block Layer I/O Scheduler Layer Request Queue Request Queue Block Device Driver Block Device Driver Kernel Space Storage Media HDD … … CD 图1 内核中块设备操作流程 页面Cache中的每页所包含的数据是属于某个文件,这个文件(准确地说是文件的 inode)就是该页的拥有者。事实上,所有的read()和write()都依赖于页面Cache;唯   6 
Linux 内核文件 Cache 机制    一的例外是当进程打开文件时,使用了O_DIRECT标志,在这种情况下,页面Cache被跳过, 且使用了进程用户态地址空间的缓冲区。有些数据库应用程序使用O_DIRECT标志,这样 他们可以使用自己的磁盘缓冲算法。 内核页面Cache的实现主要为了满足下面两种需要:  快速定位含有给定所有者相关数据的特定页。为了尽可能发挥页面Cache的优势, 查找过程必须是快速的。  记录在读或写页中的数据时,应该如何处理页面Cache中的每个页。例如,从普通 文件、块设备文件或交换区读一个数据页,必须用不同的方式;这样内核必须根据 页面拥有者来选择正确的操作。 显然,页面Cache中的数据单位是整页数据。当然一个页面中的数据在磁盘上不必是相 邻的,这样页面就不能用设备号和块号来识别。取而代之的是,Cache中的页面识别是通过 拥有者和拥有者数据中的索引,通常是inode和相应文件内的偏移量。 文件Cache是文件数据在内存中的副本,因此文件Cache管理与内存管理系统和文件系 统都相关:一方面文件 Cache 作为物理内存的一部分,需要参与物理内存的分配回收过程, 另一方面文件Cache中的数据来源于存储设备上的文件,需要通过文件系统与存储设备进行 读写交互。从操作系统的角度考虑,文件Cache可以看做是内存管理系统与文件系统之间的 联系纽带。因此,文件 Cache管理是操作系统的一个重要组成部分,它的性能直接影响着 文件系统和内存管理系统的性能。   2 Cache重要数据结构和函数 2.1 address_space 页面Cache的核心数据结构是address_space,定义在include/linux/fs.h中。 address_space结构体嵌入在拥有该页面的inode对象中。在Cache中,可能有多个页面同 属于一个inode,这样他们就可能指向同一个address_space对象。同时,通过该对象将拥 有者的页面和在这些页面上的操作方法联系起来。address_space对象中成员变量含义如表 1所示。 00664: struct aaddddrreessss__ssppaaccee {   7 
  Linux 内核文件 Cache 机制  *host; /* owner: inode, block_device */ /* radix tree of all pages */ tree_lock; /* and lock protecting it */ i_mmap_lock; /* protect tree, count, list */ i_mmap_writable;/* count VM_SHARED mappings */ /* tree of private and shared mappings */ i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ 00665: 00666: 00667: 00668: 00669: 00670: 00671: 00672: 00673: 00674: 00675: 00676: 00677: 00678: 00679: 00680: 00681: 00682: } attribute struct inode struct radix_tree_root page_tree; spinlock_t unsigned int struct prio_tree_root i_mmap; struct list_head spinlock_t unsigned int /* Protected by tree_lock together with the radix tree */ unsigned long pgoff_t const struct address_space_operations *a_ops; /* methods */ unsigned long struct backing_dev_info *backing_dev_info; /* device readahead, etc */ spinlock_t struct list_head private_list; /* ditto */ struct address_space *assoc_mapping; /* ditto */ private_lock;/* for use by the address_space */ writeback_index;/* writeback starts here */ truncate_count; /* Cover race condition with truncate */ nrpages; /* number of total pages */ flags; /* error bits/gfp mask */ ((aligned(sizeof(long)))); 每个页面描述符(struct page)包含两个成员变量mapping和index,它们是用来链接 页面到页面Cache。mapping指向inode(拥有该页面)的address_space对象;index是拥 有者“地址空间”(这种情况下可以地址空间理解为磁盘上的文件)内的偏移量,单位大小 是页。当在页面Cache中查找某个页时,就是使用成员变量mapping和index。 表1 address_space对象成员变量含义 类型 struct inode * struct radix_tree_root spinlock_t unsigned int struct prio_tree_root struct list_head spinlock_t unsigned int unsigned long unsigned long struct address_space_operations * unsigned long struct backing_dev_info * 字段 host page_tree 含义 指向拥有该对象的节点 表示拥有者的页基树(radix tree)的根 保护基树的自旋锁 tree_lock i_mmap_writable 地址空间中共享内存映射的个数 i_mmap radix优先搜索树的根 i_mmap_nonlinear 地址空间中非线性内存区的链表 i_mmap_lock 保护radix优先搜索树的自旋锁 TRuncate_count 截断文件时使用的顺序计数器 nrpages writeback_index 最后一次回写操作所作用的页索引 a_ops 对所有者页进行操作的方法 所有者的页总数 flags backing_dev_info 指向拥有者的数据所在块设备的 错误位和内存分配标志 spinlock_t struct list head private_lock private_list backing_dev_info 通常是管理private_list链表时使用的自旋锁 通常是与索引节点相关的间接快的脏缓冲区 链表 struct address_space * assoc_mapping 通常指向间接块所在块设备的 address_space对象 注意,在某些情况下,页面Cache可能包含磁盘上数据多份拷贝。因为一个普通文件的   8 
分享到:
收藏