Gitlib Gitlib
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)

Ravior

以梦为马,莫负韶华
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)
  • 操作系统

    • 学习笔记

      • 鸟哥的Linux私房菜学习笔记01-计算机概论
      • 鸟哥的Linux私房菜学习笔记02-磁盘分区
      • 鸟哥的Linux私房菜学习笔记03-日志文件
      • 寄存器
      • 汇编语言
      • 零拷贝
      • 内存管理单元MMU
      • 内存管理基础知识
      • 文件系统
      • 系统调用
      • 写时复制
      • 虚拟地址
      • 虚拟内存
      • 中断
      • CPU
      • DMA
      • mmap
      • Swap分区
    • Shell

    • Linux命令

    • RAID分类详解
    • Page Cache与Page回写
      • Block
      • Page
      • inode
        • inode的大小
        • inode号码
        • 硬链接
        • 软链接
      • Page Cache
        • 读Cache
        • 写Cache
        • Cache回收
      • Page回写
      • Buffer Cache
      • Page Cache与Buffer Cache的区别
      • 查看Cache和Buffer用量
    • 磁盘IO与swap分区
  • 计算机网络

  • 数据结构和算法

  • MySQL

  • Redis

  • Nginx

  • MongoDB

  • 其他

  • 计算机基础
  • 操作系统
Ravior
2019-04-03
目录

Page Cache与Page回写

page cache 和buffer cache 认识

在了解Page Cache之前我们先了解一下相关概念。

# Block

操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个**"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个sector组成一个 block**。

# Page

每次磁盘IO读取的数据我们称之为一页(page),一页的大小与操作系统有关,一般为4k或者8k。与Block不同,页是磁盘IO读取的数据存入到内存中的最小单位。

# inode

文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。

每一个文件都有对应的一个inode,将inode关联到文件后系统将通过inode号来识别文件,而不是文件名。并且访问文件时将先找到inode,通过inode中记录的block位置找到该文件。

# inode的大小

inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。

每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。

查看每个硬盘分区的inode总数和已经使用的数量,可以使用df命令:

gitlib@devops:~$ df -hi
Filesystem     Inodes IUsed IFree IUse% Mounted on
udev             474K   394  473K    1% /dev
tmpfs            478K  1.1K  477K    1% /run
/dev/vda1        3.2M  316K  2.9M   10% /
tmpfs            478K     7  478K    1% /dev/shm
tmpfs            478K     5  478K    1% /run/lock
tmpfs            478K    16  478K    1% /sys/fs/cgroup
tmpfs            478K     4  478K    1% /run/user/1000
1
2
3
4
5
6
7
8
9

可以用stat命令,查看某个文件的inode信息:

zhoufei@devops:~/shell$ stat check_nginx_pid.sh 
  File: 'check_nginx_pid.sh'
  Size: 293       	Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d	Inode: 370886      Links: 1
Access: (0755/-rwxr-xr-x)  Uid: ( 1000/ zhoufei)   Gid: (    0/    root)
Access: 2018-08-10 22:35:21.177008044 +0800
Modify: 2018-08-10 22:35:21.177008044 +0800
Change: 2018-08-10 22:35:30.953004155 +0800
 Birth: -
1
2
3
4
5
6
7
8
9

# inode号码

每个inode都有一个号码,操作系统用inode号码来识别不同的文件。

这里值得重复一遍,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。

表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:

  • 首先,系统找到这个文件名对应的inode号码;
  • 其次,通过inode号码,获取inode信息;
  • 最后,根据inode信息,找到文件数据所在的block,读出数据。

使用ls -i命令,可以看到文件名对应的inode号码:

gitlib@devops:~/shell$ ls -i
370886 check_nginx_pid.sh
1
2

# 硬链接

虽然每个文件都有一个inode,但是存在一种可能:多个文件的inode相同,也就即inode号、元数据、block位置都相同,这是一种什么样的情况呢?能够想象这些inode相同的文件使用的都是同一条inode记录,所以代表的都是同一个文件,这些文件所在目录的data block中的inode指针目的地都是一样的,只不过各指针对应的文件名互不相同而已。这种inode相同的文件在Linux中被称为**"硬链接"**。

硬链接文件的inode都相同,每个文件都有一个**"硬链接数"**的属性,使用ls -l的第二列就是被硬链接数,它表示的就是该文件有几个硬链接。

gitlub@devops:~/shell$ ls -l
total 4
-rwxr-xr-x 1 zhoufei root 293 Aug 10 22:35 check_nginx_pid.sh
1
2
3

每创建一个文件的硬链接,实质上是多一个指向该inode记录的inode指针,并且硬链接数加1。

删除文件的实质是删除该文件所在目录data block中的对应的inode指针,所以也是减少硬链接次数,由于block指针是存储在inode中的,所以不是真的删除数据,如果仍有其他指针指向该inode,那么该文件的block指针仍然是可用的。当硬链接次数为1时再删除文件就是真的删除文件了,此时inode记录中block指针也将被删除。

# 软链接

硬链接不能跨文件系统创建,否则inode号可能会冲突。于是实现了软链接以便跨文件系统建立链接。既然是跨文件系统,那么软链接必须得有自己的inode号。

# Page Cache

Page cache,又称pcache,其中文名称为页高速缓冲存储器,简称页高缓。它用于缓存文件的逻辑内容,从而加快对磁盘上映像和数据的访问。

Page cache由内存中的物理page组成,其内容对应磁盘上的block。一个page通常包含多个block,这些block不一定是连续的。

# 读Cache

当内核发起一个读请求时(例如进程发起read()请求),首先会检查请求的数据是否缓存到了page cache中,如果有,那么直接从内存中读取,不需要访问磁盘,这被称为cache命中(cache hit)。

如果cache中没有请求的数据,即cache未命中(cache miss),就必须从磁盘中读取数据。然后内核将读取的数据缓存到cache中,这样后续的读请求就可以命中cache了。page可以只缓存一个文件部分的内容,不需要把整个文件都缓存进来。

# 写Cache

当内核发起一个写请求时(例如进程发起write()请求),同样是直接往cache中写入,后备存储中的内容不会直接更新。内核会将被写入的page标记为dirty,并将其加入dirty list中。内核会周期性地将dirty list中的page写回到磁盘上,从而使磁盘上的数据和内存中缓存的数据一致。

# Cache回收

Page cache存储的数据在I/O完成后并不回收,而是一直保存在内存中,除非内存紧张,才开始回收占用的内存。当使用的内存超过一定阈值,就要释放内存空间。cache回收的任务是选择合适的page释放,并且如果page是dirty的,需要将page写回到磁盘中再释放。

Linux 提供了这样一个参数min_free_kbytes,用来确定系统开始回收内存的阀值,控制系统的空闲内存。值越高,内核越早开始回收内存,空闲内存越高。

gitlib@devops:~$ free 
              total        used        free      shared  buff/cache   available
Mem:        3915476     1430124      147956       44624     2337396     2132272
Swap:             0           0           0
zhoufei@devops:~$  cat /proc/sys/vm/min_free_kbytes
67584
1
2
3
4
5
6

# Page回写

Page cache是通过将磁盘中的数据缓存到内存中,从而减少磁盘I/O操作,从而提高性能。此外,还要确保在page cache中的数据更改时能够被同步到磁盘上,后者被称为page回写(page writeback)

# Buffer Cache

当应用程序需要读取文件中的数据时,操作系统先分配一些内存,将数据从存储设备读入到这些内存(Page Cache)中,然后再将数据分发给应用程序;当需要往文件中写数据时,操作系统先分配内存(Buffer Cache)接收用户数据,然后再将数据从内存写到磁盘上。

BufferCache通常1K,对应于一个磁盘块,用于减少磁盘IO.

# Page Cache与Buffer Cache的区别

  • Page Cache是内存与硬盘之间的;Buffer Cache是cpu与内存之间的;

  • Page cache 缓存了file,以优化文件的I/O,Buffer cache 缓冲了磁盘 block,以优化磁盘I/O。

  • 读文件:

可能不连续的几个磁盘块 -> pageCache -> 应用程序进程空间

  • 写文件:

应用程序进程 -> bufferCache -> 磁盘

# 查看Cache和Buffer用量

  • free命令
zhoufei@devops:~$ free 
              total        used        free      shared  buff/cache   available
Mem:        3915476     1430124      147956       44624     2337396     2132272
Swap:             0           0           0
1
2
3
4
  • cat /proc/meminfo
gitlib@devops:~$ cat /proc/meminfo 
MemTotal:        3915476 kB
MemFree:          150168 kB
MemAvailable:    2134296 kB
Buffers:           93836 kB
Cached:          1944524 kB
SwapCached:            0 kB
...
1
2
3
4
5
6
7
8
#操作系统
上次更新: 2022/12/01, 11:09:34
RAID分类详解
磁盘IO与swap分区

← RAID分类详解 磁盘IO与swap分区→

最近更新
01
常用游戏反外挂技术总结
11-27
02
Golang开发实践万字总结
11-11
03
Redis万字总结
10-30
更多文章>
Theme by Vdoing | Copyright © 2011-2022 Ravior | 粤ICP备17060229号-3 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式