Linux buffer到底是什么?和cache有什么区别?

来源:编程网作者:芒果头衔:草根站长
导读:本期聚焦于小伙伴创作的《Linux buffer到底是什么?和cache有什么区别?》,敬请观看详情。一块频繁写入的小文件让磁盘IO突然飙升,排查时发现free命令输出里buff和cache占用极高,不少人误以为内存泄漏。其实buffer是内核为块设备临时存放原始读写数据的专用内存区,主要缓存磁盘扇区级的元数据与脏页,与面向文件内容的cache不同。理解buffer的分配逻辑能避免误删进程或盲目清理内存。本文从内核角度说明buffer的归属、生命周期及查看方式,并对比cache差异,帮助准确定位性能问题。

在Linux系统中,buffer是指内核为块设备(如硬盘、SSD)分配的临时内存区域,用于缓存尚未写入磁盘或刚从磁盘读出的原始数据块。它工作在文件系统之下,直接面对扇区或块设备层,因此和我们在应用层理解的“文件内容缓存”并不是一回事。很多初学者把free命令里的buff和cache混为一谈,结果在排查内存问题时得出错误结论。

Linux buffer到底是什么?和cache有什么区别?

一、Linux buffer的底层原理

当进程通过文件系统写入数据时,内核并不会立刻把数据刷到物理磁盘。对于块设备操作,内核会先把数据放进buffer中,这些buffer以buffer_head结构描述,关联具体的设备号和块号。buffer的存在主要是为了合并相邻的小块读写、减少磁盘寻道次数,同时作为文件系统元数据(如inode、目录项)的缓存载体。

从内存管理角度看,buffer通常附着在页缓存(page cache)之上。早期内核中buffer和page cache是两套独立机制,后来统一为address_space管理,但buffer依然保留“块级缓存”的语义。我们可以用buffer_head来理解一次写操作的路径:用户数据先到page cache,若涉及元数据或裸设备读写,则生成对应buffer并标记为脏,由pdflush或现代的内核回写线程定时刷盘。

1.1 buffer与块设备的关系

buffer只关心“块”而不是“文件”。例如执行dd命令直接向/dev/sda写入,不经过文件系统,这时产生的缓存几乎全是buffer。而通过vim编辑一个文件并保存,大部分进入page cache,只有文件系统的间接块、位图等才以buffer形式存在。

这种设计让内核能在不关心文件逻辑的情况下,对磁盘做高效的批量调度。代价是我们需要通过不同工具去区分它们,而不能只看一个总和数值。

二、buffer和cache的核心区别

cache(通常指page cache)缓存的是文件内容本身,读一个文件时命中cache就不需要访问磁盘。buffer缓存的是块设备的底层数据和元数据,二者在free命令中常被合并展示,但/proc/meminfo里分开统计。

维度buffercache
缓存对象块设备原始块、文件系统元数据文件数据页
所处层次更靠近块设备层更靠近文件系统层
典型场景裸设备读写、目录遍历文件读取、程序加载

一个常见误区是认为buffer只用于写、cache只用于读,实际上两者都参与读写。比如读目录时,目录项所在的块会进buffer;读文件时文件页进cache,但文件系统的inode块同样可能进buffer。

2.1 如何查看buffer占用

使用free -w可以分开看buffers和cache,或者直接读/proc/meminfo中的Buffers和Cached字段。下面是一段简单的查看脚本:

#!/bin/bash
# 读取meminfo中的buffer与cache
buff=$(grep "^Buffers:" /proc/meminfo | awk '{print $2}')
cache=$(grep "^Cached:" /proc/meminfo | awk '{print $2}')
echo "Buffers大小为: ${buff} kB"
echo "Cached大小为: ${cache} kB"

这段代码通过grep提取内核暴露的内存信息,避免了free命令合并显示带来的混淆。在自动化监控中,建议直接采集/proc/meminfo而不是解析free输出。

三、buffer的生命周期与释放

buffer中的脏数据由内核回写线程按阈值刷盘,干净buffer在内存紧张时会被回收。手动释放一般用sysctl控制drop_caches,但生产环境需谨慎,因为强制回收会引发IO抖动。

下面示例展示如何只释放page cache(不影响buffer),以及全部释放的方式。注意命令需root权限:

# 只释放page cache
echo 1 > /proc/sys/vm/drop_caches
# 释放buffer和page cache
echo 3 > /proc/sys/vm/drop_caches

在绝大多数服务场景中,buffer占用高并不是故障,而是内核利用空闲内存提升IO效率的正常行为。只有当buffer持续增长且伴随不可回收的 pinned 内存时,才需要检查是否有进程做了大量直写块设备操作。

3.1 编程中观察buffer变化

我们可以用一段Python代码持续记录buffer变化,辅助判断某操作是否产生大量buffer:

import time

def get_buffers():
    with open('/proc/meminfo') as f:
        for line in f:
            if line.startswith('Buffers:'):
                return int(line.split()[1])
    return 0

# 循环打印buffer大小
for _ in range(5):
    print('当前Buffers:', get_buffers(), 'kB')
    time.sleep(1)

运行此类脚本配合dd写裸设备,能直观看到Buffers字段的跳变。这比单纯看监控图表更容易理解buffer的产生路径。

四、总结与实践建议

理解Linux buffer是什么,重点在于认清它“块级、元数据、裸设备”的缓存定位。和cache的文件内容缓存形成互补,共同构成Linux高效的IO栈。日常排查时不要因为buff/cache数值高就恐慌,应结合iostat、/proc/meminfo和具体业务IO模式综合分析。

如果业务大量使用数据库且开启直写或裸设备映射,buffer占比偏高属预期;若是普通Web服务,buffer异常增长往往指向日志轮转或临时文件操作问题。掌握这些区分方法,才能给出准确的容量与性能优化方案。

Linux_bufferbuffer_cachepage_cache修改时间:2026-08-09 19:30:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。