0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

buffers内存与cached内存的区别

嵌入式与Linux那些事 来源:嵌入式与Linux那些事 2024-07-29 14:17 次阅读

free 命令是Linux系统上查看内存使用状况最常用的工具,然而很少有人能说清楚 “buffers” 与 “cached” 之间的区别:

721df7b0-4d61-11ef-b8af-92fbcf53809c.png

我们先抛出结论,如果你对研究过程感兴趣可以继续阅读后面的段落:

buffers 表示块设备(block device)所占用的缓存页,包括:直接读写块设备、以及文件系统元数据(metadata),比如SuperBlock所使用的缓存页;

cached 表示普通文件数据所占用的缓存页。

下面是分析过程:

先用 strace 跟踪 free 命令,看看它是如何计算 buffers 和 cached 的:

#stracefree
...
open("/proc/meminfo",O_RDONLY)=3
lseek(3,0,SEEK_SET)=0
read(3,"MemTotal:3848656kB
MemF"...,2047)=1170
...

显然 free 命令是从 /proc/meminfo 中读取信息的,跟我们直接读到的结果一样:

#cat/proc/meminfo
MemTotal:3848656kB
MemFree:865640kB
Buffers:324432kB
Cached:2024904kB
...
SwapTotal:2031612kB
SwapFree:2031612kB
...
Shmem:5312kB
...

那么 /proc/meminfo 中的 Buffers 和 Cached 又是如何得来的呢?这回没法偷懒,只能去看源代码了。源代码文件是:fs/proc/meminfo.c ,我们感兴趣的函数是:meminfo_proc_show(),阅读得知:

Cached 来自于以下公式:

global_page_state(NR_FILE_PAGES)–total_swapcache_pages–i.bufferram

global_page_state(NR_FILE_PAGES) 表示所有的缓存页(page cache)的总和,它包括:

Cached

Buffers 也就是上面公式中的 i.bufferram,来自于 nr_blockdev_pages() 函数的返回值。

交换区缓存(swap cache)

global_page_state(NR_FILE_PAGES) 来自 vmstat[NR_FILE_PAGES],vmstat[NR_FILE_PAGES] 可以通过 /proc/vmstat 来查看,表示所有缓存页的总数量:

#cat/proc/vmstat
...
nr_file_pages587334
...

注意以上nr_file_pages是以page为单位(一个page等于4KB),而free命令是以KB为单位的。

直接修改 nr_file_pages 的内核函数是:__inc_zone_page_state(page, NR_FILE_PAGES) 和__dec_zone_page_state(page, NR_FILE_PAGES),一个用于增加,一个用于减少。

Swap Cache是什么?

用户进程的内存页分为两种:file-backed pages(与文件对应的内存页)和anonymous pages(匿名页)。匿名页(anonymous pages)是没有关联任何文件的,比如用户进程通过malloc()申请的内存页,如果发生swapping换页,它们没有关联的文件进行回写,所以只能写入到交换区里。

交换区可以包括一个或多个交换区设备(裸盘、逻辑卷、文件都可以充当交换区设备),每一个交换区设备在内存里都有对应的swap cache,可以把swap cache理解为交换区设备的page cache:page cache对应的是一个个文件,swap cache对应的是一个个交换区设备,kernel管理swap cache与管理page cache一样,用的都是radix-tree,唯一的区别是:page cache与文件的对应关系在打开文件时就确定了,而一个匿名页只有在即将被swap-out的时候才决定它会被放到哪一个交换区设备,即匿名页与swap cache的对应关系在即将被swap-out时才确立。

并不是每一个匿名页都在swap cache中,只有以下情形之一的匿名页才在:

匿名页即将被swap-out时会先被放进swap cache,但通常只存在很短暂的时间,因为紧接着在pageout完成之后它就会从swap cache中删除,毕竟swap-out的目的就是为了腾出空闲内存;【注:参见mm/vmscan.c: shrink_page_list(),它调用的add_to_swap()会把swap cache页面标记成dirty,然后它调用try_to_unmap()将页面对应的page table mapping都删除,再调用pageout()回写dirty page,最后try_to_free_swap()会把该页从swap cache中删除。】

曾经被swap-out现在又被swap-in的匿名页会在swap cache中,直到页面中的内容发生变化、或者原来用过的交换区空间被回收为止。【注:当匿名页的内容发生变化时会删除对应的swap cache,代码参见mm/swapfile.c: reuse_swap_page()。】

cached:

Cached 表示除去 buffers 和 swap cache 之外,剩下的也就是普通文件的缓存页的数量:

global_page_state(NR_FILE_PAGES)–total_swapcache_pages–i.bufferram

所以关键还是要理解 buffers 是什么含义。

buffers:

从源代码中看到,buffers 来自于 nr_blockdev_pages() 函数的返回值:

longnr_blockdev_pages(void)
{
structblock_device*bdev;
longret=0;
spin_lock(&bdev_lock);
list_for_each_entry(bdev,&all_bdevs,bd_list){
ret+=bdev->bd_inode->i_mapping->nrpages;
}
spin_unlock(&bdev_lock);
returnret;
}

这段代码的意思是遍历所有的块设备(block device),累加每个块设备的inode的i_mapping的页数,统计得到的就是 buffers。显然 buffers 是与块设备直接相关的。

那么谁会更新块设备的缓存页数量(nrpages)呢?我们继续向下看。

搜索kernel源代码发现,最终点我更新mapping->nrpages字段的函数就是:

pagemap.h:add_to_page_cache
>filemap.c:add_to_page_cache_locked
C__add_to_page_cache_locked
>page_cache_tree_insert
和:
filemap.c:delete_from_page_cache
>__delete_from_page_cache
>page_cache_tree_delete
staticinlineintadd_to_page_cache(structpage*page,
structaddress_space*mapping,pgoff_toffset,gfp_tgfp_mask)
{
interror;

__set_page_locked(page);
error=add_to_page_cache_locked(page,mapping,offset,gfp_mask);
if(unlikely(error))
__clear_page_locked(page);
returnerror;
}

voiddelete_from_page_cache(structpage*page)
{
structaddress_space*mapping=page->mapping;
void(*freepage)(structpage*);

BUG_ON(!PageLocked(page));

freepage=mapping->a_ops->freepage;
spin_lock_irq(&mapping->tree_lock);
__delete_from_page_cache(page,NULL);
spin_unlock_irq(&mapping->tree_lock);
mem_cgroup_uncharge_cache_page(page);

if(freepage)
freepage(page);
page_cache_release(page);
}

这两个函数是通用的,block device 和 文件inode 都可以调用,至于更新的是块设备的(buffers)还是文件的(cached),取决于参数变量mapping:如果mapping对应的是块设备,那么相应的统计信息会反映在 buffers 中;如果mapping对应的是文件inode,影响的就是 cached。我们下面看看kernel中哪些地方会把块设备的mapping传递进来。

首先是块设备本身,打开时使用 bdev->bd_inode->i_mapping。

staticintblkdev_open(structinode*inode,structfile*filp)
{
structblock_device*bdev;

/*
*Preservebackwardscompatibilityandallowlargefileaccess
*evenifuserspacedoesn'taskforitexplicitly.Somemkfs
*binaryneedsit.Wemightwanttodropthisworkaround
*duringanunstablebranch.
*/
filp->f_flags|=O_LARGEFILE;

if(filp->f_flags&O_NDELAY)
filp->f_mode|=FMODE_NDELAY;
if(filp->f_flags&O_EXCL)
filp->f_mode|=FMODE_EXCL;
if((filp->f_flags&O_ACCMODE)==3)
filp->f_mode|=FMODE_WRITE_IOCTL;

bdev=bd_acquire(inode);
if(bdev==NULL)
return-ENOMEM;

filp->f_mapping=bdev->bd_inode->i_mapping;

returnblkdev_get(bdev,filp->f_mode,filp);
}

其次,文件系统的Superblock也是使用块设备:

structsuper_block{
...
structblock_device*s_bdev;
...
}

intinode_init_always(structsuper_block*sb,structinode*inode)
{
...
if(sb->s_bdev){
structbacking_dev_info*bdi;

bdi=sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
mapping->backing_dev_info=bdi;
}
...
}

sb表示SuperBlock,s_bdev就是块设备。Superblock是文件系统的metadata(元数据),不属于文件,没有对应的inode,所以,对metadata操作所涉及的缓存页都只能利用块设备mapping,算入 buffers 的统计值内。

如果文件含有间接块(indirect blocks),因为间接块也属于metadata,所以走的也是块设备的mapping。查看源代码,果然如此:

ext4_get_blocks
->ext4_ind_get_blocks
->ext4_get_branch
->sb_getblk

staticinlinestructbuffer_head*
sb_getblk(structsuper_block*sb,sector_tblock)
{
return__getblk(sb->s_bdev,block,sb->s_blocksize);
}

这样我们就知道了buffers 是块设备(block device)占用的缓存页,分为两种情况:

直接对块设备进行读写操作;

文件系统的metadata(元数据),比如 SuperBlock。

验证:

现在我们来做个测试,验证一下上述结论。既然文件系统的metadata会用到 buffers,我们用 find 命令扫描文件系统,观察 buffers 增加的情况:

#free
totalusedfreesharedbufferscached
Mem:3848656288950895914853162638962023340
-/+buffers/cache:6022723246384
Swap:203161202031612

#find/-nameabc.def

#free
totalusedfreesharedbufferscached
Mem:3848656298405286460453203196122023348
-/+buffers/cache:6410923207564
Swap:203161202031612

再测试一下直接读取block device,观察buffers增加的现象:

#free
totalusedfreesharedbufferscached
Mem:3848656300694484171253163310202028648
-/+buffers/cache:6472763201380
Swap:203161202031612

#ddif=/dev/sda1of=/dev/nullcount=2000
2000+0recordsin
2000+0recordsout
1024000bytes(1.0MB)copied,0.026413s,38.8MB/s

#free
totalusedfreesharedbufferscached
Mem:3848656300770484095253163318722028692
-/+buffers/cache:6471403201516
Swap:203161202031612

结论:

free 命令所显示的 buffers 表示块设备(block device)所占用的缓存页,包括直接读写块设备、以及文件系统元数据(metadata)如SuperBlock所使用的缓存页;而 cached 表示普通文件所占用的缓存页。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    2904

    浏览量

    73557
  • Linux系统
    +关注

    关注

    4

    文章

    587

    浏览量

    27184
  • 命令
    +关注

    关注

    5

    文章

    658

    浏览量

    21931
  • Buffers
    +关注

    关注

    0

    文章

    13

    浏览量

    10412

原文标题:【内存】buffers与cached的区别

文章出处:【微信号:嵌入式与Linux那些事,微信公众号:嵌入式与Linux那些事】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    堆栈内存和堆内存之间的区别

    编写有效的代码需要了解堆栈和堆内存,这使其成为学习编程的重要组成部分。不仅如此,新程序员或职场老手都应该完全熟悉堆栈内存和堆内存之间的区别,以便编写有效且优化的代码。
    发表于 08-07 12:23 565次阅读
    堆栈<b class='flag-5'>内存</b>和堆<b class='flag-5'>内存</b>之间的<b class='flag-5'>区别</b>

    Linux上对进程进行内存分析和内存泄漏定位

    内存管理并不熟悉,不过上述说法,可以通过下面的方法来验证:一、系统内存。在proc目录下的meminfo文件描述系统内存的使用情况,可用的物理内存=memfree+
    发表于 07-09 08:15

    Linux如何设置虚拟内存

    1、打开终端,切换到root用户,输入:free -m查看内存状态[root@lxt lxt]# free -mtotal used free shared buffers cached
    发表于 07-23 07:47

    free命令介绍!内存的分类!

    上面输出的结果比较难理解的可能是第三行,为什么要向用户展示这行数据呢?内存使用量减去系统buffer/cached内存表示何意呢?系统空闲内存加上buffer/
    的头像 发表于 09-10 17:21 4690次阅读

    Linux吃掉我的内存

    系统空闲的内存buffers/cached好处 Linux 内存管理做了很多精心的设计,除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换),还采取了两种主要C
    发表于 04-02 14:32 171次阅读

    电脑中硬盘和内存区别是什么

    很多购买电脑的同学仍然还不清楚内存和硬盘到底有什么区别,在电脑里面有什么作用,容易把内存当硬盘或把硬盘当内存,下面小编通俗易懂的来给大家讲讲硬盘跟
    发表于 12-22 11:13 1w次阅读

    显存和内存有什么区别

    显存和内存有什么区别?两者有工作对象、存储速度和容量的区别。工作对象方面,显存只为GPU暂存资料,而内存则是为CPU和系统缓存资料空间;存储速度方面,GDDR6显存速度最高可达72GB
    发表于 05-19 10:46 2.2w次阅读

    内存套条和单条的区别

    同型号的内存条,套装往往要比单条还要贵一些。讲道理来说,同型号同容量同频率的内存条价格应该一样,但是实际上他们的价格是有区别的,为什么会有这样的差别呢?内存套条和单条有什么
    发表于 05-25 10:11 4781次阅读

    低电压内存和普通内存区别有哪些

    在选购笔记本的时候,有的型号会标注为低电压的内存条或者是后缀带有L,那么低电压内存和普通内存区别有哪些,下面就为大家带来相关的介绍。
    发表于 05-25 10:14 4108次阅读

    内存溢出和内存泄露的区别_内存溢出的原因以及解决方法

    内存溢出和内存泄露的区别是什么?内存溢出怎么解决?内存溢出是指程序在申请内存时,没有足够的
    发表于 06-01 10:27 2832次阅读

    nonecc内存和ecc内存区别

     ecc内存就是能够实现错误检查和纠正技术的内存条,多应用于服务器和图形工作站上。
    的头像 发表于 09-19 16:18 1.4w次阅读

    内存和硬盘的区别与作用

    在定义方面它们有本质的区别,硬盘属于“ 非易失性存储器”,而内存是“随机存取存储器”,属于“易失性存储设备“。
    发表于 05-17 15:40 2460次阅读

    内存与外存的关键区别

    内存和外存是计算机存储的两种不同形式,两者虽然都是存储数据的方式,但是却有许多区别。本文将从定义、结构、速度、容量、使用、价格等方面探讨内存与外存的关键区别
    的头像 发表于 06-10 15:06 6548次阅读

    内存溢出与内存泄漏:定义、区别与解决方案

    内存溢出与内存泄漏:定义、区别与解决方案  内存溢出和内存泄漏是计算机科学中常见的问题,在开发和调试过程中经常会遇到。本文将详细介绍
    的头像 发表于 12-19 14:10 1851次阅读

    系统内存和运行内存区别

    区别。 首先,系统内存是指计算机中存储程序和数据的硬件设备,也被称为主存或内存条。它是计算机用来临时存储数据和指令的地方,相当于计算机的“大脑”。系统内存的容量通常以GB(Gigab
    的头像 发表于 01-15 16:32 2391次阅读