Linux free命令介绍、buffer和cache的区别、缓存等

0    1885    14

Tags:

👉 本文共约9934个字,系统预计阅读时间或需38分钟。

Linux free命令用于显示内存状态。

free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。

free输出示例

Linux 6下:

free的默认显示单位是kb

在linux 6中,我们看到free命令有三行内容:Mem,-/+ buffers/cache,Swap,代表的内容如下:

名称代表的内容
Mem内存的使用情况。total代表总的内存大小, used 代表程序已经使用的内存大小,free代表的是空闲的内存大小, shared 代表的是共享内存,buffers 代表的是 buffers cache缓冲(即将要写入磁盘), cached 代表的是 Page cache缓存(从磁盘读取到内存).
-/+ buffers/cache表示物理内存已用多少,可用多少。used 代表的除去buffers和cached实际程序占用的内存, free代表的是“ total - 第二行used”, 也就是 “第一行free + 第一行buffers + 第一行cached”
Swap交换空间(虚拟内存)的使用情况

示例:

在以上这个系统中,物理内存128g,内存其实真实才用了17G左右,而不是70g。

Linux 7下:

centos7 的free 命令多了一个 -h 参数,它会自动根据内存的大小,自动转换成合适的单位,默认的计算倍数是 1024 。free 的显示信息来自于/proc/meminfo,常用参数:

-h 以人性化显示
--si 指定计算倍数为1000.
-b 指定单位为bytes
-m 指定单位为mb
-k 指定单位为kb,默认单位
-g 指定单位为gb
-t 显示物理内存和虚拟内存的总和
-s n 每隔n秒显示一次
-c 显示多少次
-V 显示free的版本信息并退出
-l 显示最低和最高的内存数据统计
-w 将buff和cacher 分开显示,默认是在一起显示的。

先说明一些基本概念
第一列
Mem 内存的使用信息
Swap 交换空间的使用信息
第一行
total 系统总的可用物理内存大小
used 已被使用的物理内存大小
free 还有多少物理内存可用
shared 被共享使用的物理内存大小
buff/cache 被 buffer 和 cache 使用的物理内存大小
available 还可以被 应用程序 使用的物理内存大小

total 代表的总的内存 (对应/proc/meminfo 里的MemTotal)
used 代表的是 已经使用的内存
free 是代表空闲的内存(对应/proc/meminfo 里的MemFree)
shared 代表的是共享的内存(对应/proc/meminfo 里的Shmem)
buff/cache 代表的是 buff(对应/proc/meminfo里的Buffers)和cache的内存(对应/proc/meminfo 里的Cached and Slab),
available 代表的是 活跃的内存
(官方文档对于available这样写到:Estimation of how much memory is available for starting new applications, without swapping. Unlike the data provided by the cache or free fields, this field takes into account page cache and also that not all reclaimable memory slabs will be reclaimed due to items being in use (MemAvailable in /proc/meminfo, available on kernels 3.14, emulated on kernels 2.6.27+, otherwise the same as free)
) available 代表的是一个新的应用程序可以使用内存的估计值,它不等于 free + buff/cache ,因为在centos 7中并不是所有的buffer/cache空间都可以被回收。

free命令的选项

在linux环境下,使用man命令、--help命令、info命令可查询free命令的所有选项,以--help为例,如:

Linux free命令介绍、buffer和cache的区别、缓存等

现在对free命令的所有选项分别进行解释:

注意:free命令的选项区分大小写,请认真对照上图中是大写还是小写

  1. free -b:以bytes为单位来显示内存的信息。

Linux free命令介绍、buffer和cache的区别、缓存等

  1. free -k:以kb为单位来显示内存的信息。

    Linux free命令介绍、buffer和cache的区别、缓存等

  2. free -m:以m为单位来显示内存的信息。

    Linux free命令介绍、buffer和cache的区别、缓存等

  3. free -g:以G为单位来显示内存的信息。

    Linux free命令介绍、buffer和cache的区别、缓存等

  4. free -h:以适于人类可读方式显示内存信息。-h与其他命令最大不同是-h选项会在数字后面加上适于人类可读的单位

Linux free命令介绍、buffer和cache的区别、缓存等

  如我们一起看到的,在1,0数字后这里是G(GB)字母。当数字并没有达到GB时,free足够聪明来知道并在每个数字后面跟上合适的单位。后面的M - 数字929告诉我们它有929MB(译注: 原文为929 number tell us its 969 Megabytes,这里应该为输入错误)。

  1. free -l:显示高低内存的利用率。

    Linux free命令介绍、buffer和cache的区别、缓存等

  2. free -t:显示linux的全部内存。

  如果我们需要每列的总计信息,我们可以在 free 命令后面跟上 -t 选项。这会在字底部额外加入一行显示。

Linux free命令介绍、buffer和cache的区别、缓存等

  1. free -s N:表示每隔N秒打印一次内存信息,直到用ctrl+c结束

    Linux free命令介绍、buffer和cache的区别、缓存等

  2. free -c N:表示重复打印内存信息N次

Linux free命令介绍、buffer和cache的区别、缓存等

  1. free -w :wide output

    Linux free命令介绍、buffer和cache的区别、缓存等

  2. free -V :显示版本信息

Linux free命令介绍、buffer和cache的区别、缓存等

free命令的选项是可以组合的,举例如下

free -hs 3: 以人类可读的方式,每隔3s打印一次内存信息,直到ctrl+c结束

Linux free命令介绍、buffer和cache的区别、缓存等

free -s 2 -c 4:每隔2秒打印一次内存信息,共打印4次

Linux free命令介绍、buffer和cache的区别、缓存等

free 与 available 的区别

free 是真正尚未被使用的物理内存大小。
available 是还可以被应用程序使用的内存大小,available = free + buffer + cache (注:只是大概的计算方法,实际中的数据往往有较大的误差)

Linux 为了提升读写性能,会消耗一部分内存资源缓存磁盘数据,对于内核来说,buffer 和 cache 其实都属于已经被使用的内存。但当应用程序申请内存时,如果 free 内存不够,内核就会回收 buffer 和 cache 的内存来满足应用程序的请求。

buffer和cache的区别

buffer和cache是两个在计算机技术中被用滥的名词,放在不通语境下会有不同的意义。

先来一幅图:

Linux free命令介绍、buffer和cache的区别、缓存等

在Linux的内存管理中,这里的buffer指Linux内存的Buffer cache。这里的cache指Linux内存中的Page cache。

  • Buffer名为缓冲,是指将要被写入磁盘的缓冲区的数据(在写入磁盘前的存储在内存中的内容),Buffer在操作系统中指Buffer cache, 中文一般翻译为 "缓冲区"。

  • Cache名为缓存,是从磁盘读取到缓存的数据,指 CPU 和内存之间高速缓存。Cache在操作系统中指 Page Cache,中文一般翻译为 "页高速缓存"或缓冲区缓存或页面缓存。注意,Cache 只有块的概念而没有文件的概念,它只是把磁盘上的块直接搬到内存中而不关心块中究竟存放的是什么格式的文件。

Page Cache

Page Cache:文件系统层级的缓存,从磁盘里读取内容时存储到这里,这样程序读取磁盘内容就会非常快,比如使用grep和find等命令查找内容和文件时,第一次会慢很多,再次执行就快好多倍,几乎是瞬间。但如上所说,如果对文件的更新不关心,就没必要清cache,否则如果要实施同步,必须要把内存空间中的cache clean下。

Page cache主要用来作为文件系统上的文件数据的缓存来用,尤其是针对当进程对文件有read/write操作的时候。如果你仔细想想的话,作为可以映射文件到内存的系统调用:mmap是不是很自然的也应该用到page cache?在当前的系统实现里,page cache也被作为其它文件类型的缓存设备来用,所以事实上page cache也负责了大部分的块设备文件的缓存工作。

Buffer Cache

Buffers 指的是 Memory used by kernel buffers(磁盘等块设备的缓冲) ,buffers 的字面意思就是缓冲,缓冲存在的目的是为了解决从速度快的地方往速度慢的地方输出东西,缓冲经常用于像 内存写入数据到磁盘,寄存器数据写到内存等等。位于内存buffer中的数据不是即时写入磁盘,而是系统空闲或者buffer达到一定大小统一写到磁盘中,所以断电易失,为了防止数据丢失所以我们最好正常关机或者多执行几次sync命令,让位于buffer上的数据立刻写到磁盘里。

Buffer cache则主要是设计用来在系统对块设备进行读写的时候,对块进行数据缓存的系统来使用。这意味着某些对块的操作会使用buffer cache进行缓存,比如我们在格式化文件系统的时候。一般情况下两个缓存系统是一起配合使用的,比如当我们对一个文件进行写操作的时候,page cache的内容会被改变,而buffer cache则可以用来将page标记为不同的缓冲区,并记录是哪一个缓冲区被修改了。这样,内核在后续执行脏数据的回写(writeback)时,就不用将整个page写回,而只需要写回修改的部分即可。

本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

释放Cache(回收cache)

为什么要清除 buffers 和caches?

因为caches是缓存的一些数据,当我们实际的数据内容已经更新了的话,那么当我们需要获取最新的数据时候,我们就需要清除caches里面的内容。或者当我们的内存的不足(将被耗尽)时,那么系统会自动清除buffers 和caches ,以满足程序对内存的需求。

Linux内核会在内存将要耗尽的时候,触发内存回收的工作,以便释放出内存给急需内存的进程使用。一般情况下,这个操作中主要的内存释放都来自于对buffer/cache的释放。尤其是被使用更多的cache空间。既然它主要用来做缓存,只是在内存够用的时候加快进程对文件的读写速度,那么在内存压力较大的情况下,当然有必要清空释放cache,作为free空间分给相关进程使用。所以一般情况下,我们认为buffer/cache空间可以被释放,这个理解是正确的。

但是这种清缓存的工作也并不是没有成本。理解cache是干什么的就可以明白清缓存必须保证cache中的数据跟对应文件中的数据一致,才能对cache进行释放。所以伴随着cache清除的行为的,一般都是系统IO飙高。因为内核要对比cache中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回,之后才能回收。

如何手工释放Cache

在系统中除了内存将被耗尽的时候可以清缓存以外,我们还可以使用下面这个命令来人工触发缓存清除的操作::

注意:在生产环境释放cache要慎重,避免引起性能抖动!

当然,这个文件可以设置的值分别为 1 、 2 、 3 。它们所表示的含义为:

echo 1 > /proc/sys/vm/drop_caches

表示仅清除页面缓存(PageCache) 。

echo 2 > /proc/sys/vm/drop_caches

表示清除回收 slab 分配器中的对象(包括目录项缓存和 inode 缓存)。 slab 分配器是内核中管理内存的一种机制,其中很多缓存数据实现都是用的 pagecache 。

echo 3 > /proc/sys/vm/drop_caches
表示清除 pagecache 和 slab 分配器中的缓存对象(包括目录项缓存和 inode 缓存)。

写入到drop_cache将清空缓存而不会杀死任何应用程序/服务。

如果你必须清除磁盘高速缓存,第一个命令在企业和生产环境中是最安全,"...echo 1> ..."只会清除页面缓存。 在生产环境中不建议使用上面的第三个选项"...echo 3 > ..." ,除非你明确自己在做什么,因为它会清除缓存页,目录项和inodes。

Linux free命令介绍、buffer和cache的区别、缓存等

Page Cache(页高速缓存)对普通文件的缓存我们可以这样理解:当内核要读一个文件(比如 /etc/hosts)时,它会先检查这个文件的数据是不是已经在页高速缓存中了。如果在,就放弃访问磁盘,直接从内存中读取。这个行为称为缓存命中。如果数据不在缓存中,就是未命中缓存,此时内核就要调度块 I/O 操作从磁盘去读取数据。然后内核将读来的数据放入页高速缓存中。这种缓存的目标是文件系统可以识别的文件(比如 /etc/hosts)。

示例

cache都能被回收么?

有关tmpfs和shm共享内存请参考:https://www.xmmup.com/linuxzhongdeshmhetmpfsjieshao.html

我们分析了cache能被回收的情况,那么有没有不能被回收的cache呢?当然有。我们先来看第一种情况:

tmpfs

大家知道Linux提供一种“临时”文件系统叫做tmpfs,它可以将内存的一部分空间拿来当做文件系统使用,使内存空间可以当做目录文件来用。现在绝大多数Linux系统都有一个叫做/dev/shm的tmpfs目录,就是这样一种存在。当然,我们也可以手工创建一个自己的tmpfs,方法如下:

于是我们就创建了一个新的tmpfs,空间是20G,我们可以在/tmp/tmpfs中创建一个20G以内的文件。如果我们创建的文件实际占用的空间是内存的话,那么这些数据应该占用内存空间的什么部分呢?根据pagecache的实现功能可以理解,既然是某种文件系统,那么自然该使用pagecache的空间来管理。我们试试是不是这样?

我们在tmpfs目录下创建了一个13G的文件,并通过前后free命令的对比发现,cached增长了13G,说明这个文件确实放在了内存里并且内核使用的是cache作为存储。再看看我们关心的指标:-/+ buffers/cache那一行。我们发现,在这种情况下free命令仍然提示我们有110G内存可用,但是真的有这么多么?我们可以人工触发内存回收看看现在到底能回收多少内存:

可以看到,cached占用的空间并没有像我们想象的那样完全被释放,其中13G的空间仍然被/tmp/tmpfs中的文件占用的。当然,我的系统中还有其他不可释放的cache占用着其余16G内存空间。那么tmpfs占用的cache空间什么时候会被释放呢?是在其文件被删除的时候.如果不删除文件,无论内存耗尽到什么程度,内核都不会自动帮你把tmpfs中的文件删除来释放cache空间。

这是我们分析的第一种cache不能被回收的情况。还有其他情况,比如:

共享内存shm

共享内存是系统提供给我们的一种常用的进程间通信(IPC)方式,但是这种通信方式不能在shell中申请和使用,所以我们需要一个简单的测试程序,代码如下:

程序功能很简单,就是申请一段不到2G共享内存,然后打开一个子进程对这段共享内存做一个初始化操作,父进程等子进程初始化完之后输出一下共享内存的内容,然后退出。但是退出之前并没有删除这段共享内存。我们来看看这个程序执行前后的内存使用:

结果是仍然不可回收。大家可以观察到,这段共享内存即使没人使用,仍然会长期存放在cache中,直到其被删除。删除方法有两种,一种是程序中使用shmctl()去IPC_RMID,另一种是使用ipcrm命令。我们来删除试试:

删除共享内存后,cache被正常释放了。这个行为与tmpfs的逻辑类似。内核底层在实现共享内存(shm)、消息队列(msg)和信号量数组(sem)这些POSIX:XSI的IPC机制的内存存储时,使用的都是tmpfs。这也是为什么共享内存的操作逻辑与tmpfs类似的原因。当然,一般情况下是shm占用的内存更多,所以我们在此重点强调共享内存的使用。

oracle的sga就是使用的这部分内存,请参考:https://www.xmmup.com/linuxzhongdeshmhetmpfsjieshao.html

说到共享内存,Linux还给我们提供了另外一种共享内存的方法,就是:

mmap

mmap()是一个非常重要的系统调用,这仅从mmap本身的功能描述上是看不出来的。从字面上看,mmap就是将一个文件映射进进程的虚拟内存地址,之后就可以通过操作内存的方式对文件的内容进行操作。但是实际上这个调用的用途是很广泛的。当malloc申请内存时,小段内存内核使用sbrk处理,而大段内存就会使用mmap。当系统调用exec族函数执行时,因为其本质上是将一个可执行文件加载到内存执行,所以内核很自然的就可以使用mmap方式进行处理。我们在此仅仅考虑一种情况,就是使用mmap进行共享内存的申请时,会不会跟shmget()一样也使用cache?

同样,我们也需要一个简单的测试程序:

这次我们干脆不用什么父子进程的方式了,就一个进程,申请一段2G的mmap共享内存,然后初始化这段空间之后等待100秒,再解除影射所以我们需要在它sleep这100秒内检查我们的系统内存使用,看看它用的是什么空间?当然在这之前要先创建一个2G的文件./mmapfile。结果如下:

然后执行测试程序:

我们可以看到,在程序执行期间,cached一直为18G,比之前涨了2G,并且此时这段cache仍然无法被回收。然后我们等待100秒之后程序结束。

程序退出之后,cached占用的空间被释放。这样我们可以看到,使用mmap申请标志状态为MAP_SHARED的内存,内核也是使用的cache进行存储的。在进程对相关内存没有释放之前,这段cache也是不能被正常释放的。实际上,mmap的MAP_SHARED方式申请的内存,在内核中也是由tmpfs实现的。由此我们也可以推测,由于共享库的只读部分在内存中都是以mmap的MAP_SHARED方式进行管理,实际上它们也都是要占用cache且无法被释放的。

查看缓存命中率

BCC工具中的cachestat和cachetop分别用来查看整个系统的缓存读写命中情况、每个进程的缓存命中情况。

cachetop和cachestat的安装方法:

示例:

TOTAL ,表示总的 I/O 次数;

MISSES ,表示缓存未命中的次数;

HITS ,表示缓存命中的次数;

DIRTIES, 表示新增到缓存中的脏页数;

BUFFERS_MB 表示 Buffers 的大小,以 MB 为单位;

CACHED_MB 表示 Cache 的大小,以 MB 为单位。

它的输出跟 top 类似,默认按照缓存的命中次数(HITS)排序,展示了每个进程的缓存命中情况。具体到每一个指标,这里的 HITS、MISSES和DIRTIES ,跟 cachestat 里的含义一样,分别代表间隔时间内的缓存命中次数、未命中次数以及新增到缓存中的脏页数。

而 READ_HIT 和 WRITE_HIT ,分别表示读和写的缓存命中率。

如何查看 Linux 当前缓存了哪些大文件?

github:https://github.com/silenceshell/hcache

Linux 用户可能经常遇到的一个问题是,机器有 16GB 内存之多,运行的进程也不多,但是剩下的 free 内存并不多,大部分都被 buff 和 cache 占用了(比如下面我的 PC)。

虽然对于 Linux 的内存分配机制来说,这种被 buff 和 cache 占用的内存在系统需要时会及时释放出来,但是有时候我们想知道到底 cache 了些什么却没有一个好的办法。

前几天看到有个人用 go 写了个 pcstat,可以查看某个文件是否被缓存(作者的目的是数据库调优),也可以根据进程的 PID 来查看都缓存了哪些文件,不过该工具不能查看整个操作系统都 cache 了哪些文件。

因此,我基于 pcstat 写了个 hcache,增加了查看当前操作系统所 cache 的前若干个文件的特性,你可以从这里下载下来试用。如果有什么建议的话也欢迎反馈给我:hubottle@gmail.com 。

使用方法比较简单:

让我们来查看一下其中列出的一个文件:

默认情况下会显示 cache 的文件的全路径,会比较长,也可以使用 --bname 选项来仅显示文件名:

这个小工具的源码开源在 Github上:hcache,欢迎关注和提交 issue 及 PR。

文件的缓存大小

指文件在内存中的缓存大小,可以使用 pcstat 这个工具,来查看文件在内存中的缓存大小以及缓存比例。

pcstat用来查看一个文件的缓存大小:

pcstat 是一个基于 Go 语言开发的工具,所以安装它之前,你首先应该安装 Go 语言,pcstat的安装方法:

在测试文件读写性能的时候,要清理缓存:

交换空间(swap space)

参考:https://www.xmmup.com/linuxzhongdejiaohuanfenquswap.html

总结

1.buffer和cache都是为了解决互访的两种设备存在速率差异,使磁盘的IO的读写性能或cpu更加高效,减少进程间通信等待的时间。

2.buffer(缓冲):用于存储速度不同步的设备或优先级不同的设备之间传输数据,通过buffer可以减少进程间通信需要等待的时间,当存储速度快的设备与存储速度慢的设备进行通信时,存储快的设备先把数据缓存到buffer上,等到系统统一把buffer上的数据写到速度慢的设备上。常见的有把内存的数据往磁盘进行写操作。

3.cache(缓存):用于对读取速度比较严格,却因为设备间因为存储设备存在速度差异,而不能立刻获取数据,这时cache就会为了加速缓存一部分数据。常见的是CPU和内存之间的数据通信,因为CPU的速度远远高于主内存的速度,CPU从内存中读取数据需等待很长的时间,而Cache保存着CPU刚用过的数据或循环使用的部分数据,这时Cache中读取数据会更快,减少了CPU等待的时间,提高了系统的性能。

4.Linux系统内存中的cache并不是在所有情况下都能被释放当做空闲空间用的。并且即使可以释放cache,也并不是对系统来说没有成本的。总结一下要点:

  • 当cache作为文件缓存被释放的时候会引发IO变高,这是cache加快文件访问速度所要付出的成本。
  • tmpfs中存储的文件会占用cache空间,除非文件删除否则这个cache不会被自动释放。
  • 使用shmget方式申请的共享内存会占用cache空间,除非共享内存被ipcrm或者使用shmctl去IPC_RMID,否则相关的cache空间都不会被自动释放。
  • 使用mmap方法申请的MAP_SHARED标志的内存会占用cache空间,除非进程将这段内存munmap,否则相关的cache空间都不会被自动释放。
  • 实际上shmget、mmap的共享内存,在内核层都是通过tmpfs实现的,tmpfs实现的存储用的都是cache。

参考

https://linux.cn/article-8532-1.html

https://www.lmlphp.com/user/2256/article/item/25751/

https://www.cnblogs.com/tjudzj/p/10100088.html

https://blog.csdn.net/ouyang_peng/article/details/84292776

https://mp.weixin.qq.com/s/ScGi3bJGW8CiWJ9PZkkEPQ

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

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

1 × 2 =

 

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部