Linux系统的Swap Buffer和Cache

在Linux系统中,我们经常用free命令来查看系统内存的使用状态。在一个 CoreOS 的系统上,free命令的显示内容大概是这样一个状态:

core@localhost ~ $ free
              total        used        free      shared  buff/cache   available
Mem:        8145320      391200     333888      204616      7420232     311660
Swap:             0           0           0
这里的默认显示单位是kb,我们可以通过添加-h参数,来让free 命令显示的更为友好一些。
core@localhost ~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.8Gi       381Mi       0.3Gi       199Mi       7.4Gi       0.3Gi
Swap:            0B          0B          0B
新版linux相对来说已经好很多了,在老版的时候,是没有available字段的。 所以放当时来说,大家可能会有下面几种反应:
  1. 对于不太了解linux系统的人来说,看到 free 之后,会觉得内存用了好多,我都没跑什么程序,内存就用完了!Linux好占内存!
  2. 稍微了解linux,并在百度搜索过相关知识的人也许会说,嗯,看起来free是没有多少了,但是真实内存才用了 400Mi 不到,还有很多剩余内存可用。buff/cache 占用比较多,说明系统中有进程曾经读写过文件,但是不要紧,这部分内存在系统内存吃紧的时候会释放出来的。

但是,上面两种说法都有些片面了,都不是很正确。接下来让我们重新来认识一下buffcache

什么是 buff/cache?

Linux 2.4的内存管理中,buffer指Linux内存的:Buffer cachecache指Linux内存中的:Page cache。一般呢,是这么解释两者的。

  • A buffer is someting that has yet to be ‘written’ to disk.
  • A cache is someting that has been ‘read’ from the disk and stored for later use.

翻译过来就是说:

  1. buffer(buff) 是用来缓存尚未“写入”磁盘的内容。
  2. cache 是用来缓存从磁盘“读取”出来的东西。

所以 buffer 被用来当成对io设备写的缓存。而 cache 被用来当作对io设备的读缓存。这里的io设备,主要指的是块设备文件和文件系统上的普通文件。

但是在 Linux 2.6 以后,它们的意义不一样了。
Linux 2.6之后Linux将他们统一合并到了Page cache作为文件层的缓存。而buffer则被用作block层的缓存。 block层的缓存是什么意思呢,你可以认为一个buffer是一个physical disk block在内存的代表,用来将内存中的pages映射为disk blocks,这部分被使用的内存被叫做buffer

buffer里面的pages,指的是Page cache中的pages,所以,buffer也可以被认为Page cache的一部分。

或者简单来说,buffer负责裸设备相关的缓存,cache负责文件系统的缓存。

Buffer 的具体职责

在当前的系统实现里,buffer主要是设计用来在系统对块设备进行读写时作为缓存来使用。这意味着对块的操作会使用buffer进行缓存,比如我们在格式化文件系统的时候。


但是一般情况下两个缓存系统是一起配合使用的,比如当我们对一个文件进行写操作的时候,cache的内容会被改变,而buffer则用来将cachepage标记为不同的缓冲区,并记录是哪一个缓冲区被修改了。

这样,内核在后续执行脏数据的回写(writeback)时,就不用将整个page写回,而只需要写回修改的部分即可。

Cache 的具体职责

cache主要用来作为文件系统上的文件数据的缓存来用,当进程对文件有read/write操作的时候。包括将文件映射到内存的系统调用mmap,就会用到cache


因为cache被作为文件类型的缓存来用,所以事实上也负责了大部分的块设备文件的缓存工作。

怎么回收 buff/cache?

Linux内核会在内存将要耗尽的时候,自动触发内存回收的工作,以便释放出内存给急需内存的进程使用。


但是这种回收的工作也并不是没有成本。

理解cache是干什么的就知道,cache中存在着一部分write操作的数据。所以必须保证cache中的数据跟对应文件中的数据一致,才能对cache进行释放。

于是伴随着cache清除的行为的,一般都是系统IO飙高。这是因为内核要将cache中缓存的write数据进行回写。

我们可以使用下面这个文件来人工触发缓存清除的操作,Linux 提供了三种清空方式:
  1. echo 1 > /proc/sys/vm/drop_caches # 仅清除页面缓存
  2. echo 2 > /proc/sys/vm/drop_caches # 清除目录项和inode
  3. echo 3 > /proc/sys/vm/drop_caches # 清除页面缓存、目录项以及inode

但是这种放时只能在执行的当时起作用,过一段时间之后又会发现内存被占满,怎么办呢?


实际上内核提供了vm.vfs_cache_pressure参数用来控制缓冲区的回收频率,我们可以调整它。

这个参数是用来控制内核回收VFS缓存的频率。修改这个值会提高或者降低回收VFS缓存的频率。值可以设置为0-200中的任意值。越大回收频率越快,可以把vm.vfs_cache_pressure赋值为200来获得最快的回收频率。这个值默认值一般为100

另外也可以使用slabtop分析内存使用情况。一般情况下,dentry*_inode_cache值越高回收的效果越好。

为什么是dentry*_inode_cache呢,这是因为当读写文件时内核会为该文件对象建立一个dentry,并将其缓存起来,方便下一次读写时直接从内存中取出提高效率。至于*_inode_cache我就不是很清楚了,只知道是为了加快对索引节点的索引,如果有清楚的可以告诉我一下。

测试一下

 

  • 首先,我们先看一下目前的内存使用量

 

core@localhost ~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.8Gi       383Mi       7.1Gi       199Mi       291Mi       7.0Gi
Swap:            0B          0B          0B
  1. 生成一个文件测试一下
core@localhost ~ $ dd if=/dev/zero of=testfile bs=1M count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 1.39192 s, 753 MB/s
  1. 检查一下内存的使用情况,是否和上面介绍的一样
core@localhost ~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.8Gi       383Mi       6.1Gi       199Mi       1.3Gi       7.0Gi
Swap:            0B          0B          0B
  1. 手动执行一下释放,看能否将内存释放出来
core@localhost ~ $ echo 1 | sudo tee /proc/sys/vm/drop_caches
1
  1. 检查一下内存是否被释放掉
core@localhost ~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.8Gi       383Mi       7.1Gi       199Mi       291Mi       7.0Gi
Swap:            0B          0B          0B
  1. 继续测试一下读取文件
core@localhost ~ $ time -p cat testfile > /dev/null
real 0.39
user 0.00
sys 0.27
  1. 可以看到用时 0.39s,我们看下内存使用
core@localhost ~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.8Gi       382Mi       6.1Gi       199Mi       1.3Gi       7.0Gi
Swap:            0B          0B          0B
  1. 然后我们再次执行一下读取文件
core@localhost ~ $ time -p cat testfile > /dev/null
real 0.17
user 0.00
sys 0.17
  1. 可以看到用时缩短到了 0.17s,这里需要说明一下的时由于我这边时固态硬盘,所以差距没这么大,如果是机械硬盘的话差距会进一步扩大。

 

[c-alert type=”info”]

红帽官方说明:

为什么缓存会占用如此多的内存?

  • 根据 Linux 虚拟内存管理器,这种行为是正常的。要理解为什么高速缓存会变得如此之高,以及为什么这不是一个问题,必须了解 I/O 在 Linux 上的工作原理。当用户进程读取或写入文件时,它实际上是在主内存中修改该文件的副本。内核从磁盘创建该副本,并在必要时将更改写回其中。这些副本占用的内存称为缓存内存。
  • 每当用户进程发起读取或写入时,都会消耗缓存内存。内核将查找用户正在操作的文件部分的副本,如果不存在这样的副本,它将分配一页新的高速缓存内存,并用从磁盘读取的适当内容填充它。如果用户只读取文件,则该页面将被标记为“干净”的缓存页面。然而,一旦用户写入文件,该页面就会被标记为“脏”。 ps 中出现的一个名为 pdflush 的内核线程将定期唤醒,并将所有标记为脏的页面复制回磁盘,然后再次将它们标记为干净。请注意,该页面仅被重新标记为干净,该页面在写回时不会被释放,但会保留下来,以防某些东西想要对其缓存的文件部分进行进一步的 IO。
  • 仅当内核需要内存用于其他用途时,才会再次释放缓存页面。因为已经从磁盘读取缓存页可以加速 I/O,并且因为摆脱干净的缓存页与分配空闲页一样容易,并且因为空闲页对帮助系统执行和运行没有任何帮助,没有理由将缓存页变成空闲页。如果内存被缓存页面填满,下次内核需要内存时,它将简单地逐出最近最少使用的干净缓存页面并重新利用它们。

[/c-alert]

原创文章,作者:AIRF,如若转载,请注明出处:http://www.ai-rf.com/index.php/2022/10/01/%e6%89%8b%e5%8a%a8%e9%87%8a%e6%94%belinux%e4%b8%8a%e7%9a%84swap%e3%80%81buffer%e5%92%8ccache/

(0)
AIRFAIRF
上一篇 2022年9月29日
下一篇 2022年10月1日

相关推荐

  • Linux exec指令

    Linux exec指令 exec是Linux Shell中一个非常重要的内建命令,用于替换当前shell的进程空间,执行指定命令或脚本而不启动新的子进程。理解和灵活运用exec对…

    Linux 2024年12月25日
  • Nginx的负载均衡实现

    环境 主机 ip 用途 软件 web1 192.168.50.60 nginx-1 httpd web2 192.168.50.61 nginx-2 httpd proxy 192…

    C_C++_C# 2023年12月16日
  • Linux系统init: prefdm main process terminated with status问题

    问题描述 服务器开机后无法正常进入桌面,查看prefdm服务是负责桌面的,故考虑进入字符界面再次尝试 问题处理 考虑从字符界面进入,进入单用户修改/etc/inttab1.进入单用…

    Linux 2022年8月1日
  • 跳转链接测试

    诺言资源网 百度

    首页 2022年9月24日
  • Linux 上保护 SSH 服务器连接的 8 种方法

    SSH 是一种广泛使用的协议,用于安全地访问 Linux 服务器。大多数用户使用默认设置的 SSH 连接来连接到远程服务器。但是,不安全的默认配置也会带来各种安全风险。 具有开放 …

    Linux 2023年11月20日
  • Linux系统操作系统网卡漂移解决方案及问题原因

    一.问题描述 公司有100-150台服务器安装RHEL7.4&中标麒麟7.4系统,为方便编辑配置网卡,使用脚本方式配置为biosname=0,ifname=0,目的是为将e…

    Linux 2021年11月21日
  • Linux中free命令有哪些高级用法

    在Linux操作系统中,free命令是一款强大的系统工具,用于查看和监控系统内存的使用情况。本文将介绍free命令的基础用法,包括查看内存总量、已使用量和可用量等信息。此外,还将探…

    C_C++_C# 2024年1月24日
  • CPU利用率高又看不到占用率高的进程?

    两步大法 1、安装unhide 安装epel源:yum -y install epel-release 安装unhide:yum -y install unhide 2、查找隐藏进…

    2023年5月9日
  • Linux系统ssh连接无响应

    一.问题描述 某集群数据节点服务器频繁无法连接,服务器间出现可ping通但ssh无法连接的情况,使用带外地址登录后远程控制也无法显示正常界面,重启后会短暂恢复。 二.排查问题 重启…

    Linux 2021年11月21日
  • 监控网卡实时流量脚本

    使用方法:./x.sh 网卡名 #!/bin/bash NIC=$1 echo -e ” In —— Out” while true; do OLD_IN=$(awk ‘$…

    2022年2月14日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注