Linux学习笔记(十二)--用户缓冲区

用户缓冲区

在Linux操作系统中,用户缓冲区是应用程序在用户空间内维护的一块内存区域,用于临时存储待写入文件或网络的数据,或从文件/网络读取的数据。它的主要目的是减少系统调用次数,提高I/O效率。

用户缓冲区的类型

先来一段代码研究一下

复制代码
#include<stdio.h>
#include<string.h>

int main()
{
    const char *msg0="hello printf\n";
    const char *msg1="hello fwrite\n";
    const char *msg2="hello write\n";

    printf("%s", msg0);
    fwrite(msg1, strlen(msg0), 1, stdout);
    write(1, msg2, strlen(msg2));

    fork();

    return 0;
}

当代码运行之后结果是

复制代码
hello printf
hello fwrite
hello write

但当我们对进程实现输出重定向(./hello > file)时,结果变成

复制代码
hello write
hello printf
hello fwrite
hello printf
hello fwrite

两次结果不一致,这是因为printf和fwrite函数都输出了两次,write只输出了一次。这与fork有关,C库函数的缓冲机制与系统调用存在显著差异。库函数如printffwrite等,在输出到文件时采用全缓冲,而输出到显示器时通常采用行缓冲,当发生重定向时,缓冲方式会发生改变。相比之下,系统调用write没有内置缓冲机制,会立即执行写入操作。这种差异在实际编程中会带来重要的行为差异。例如,当程序调用fork()创建子进程时,由于写时拷贝机制的存在,父子进程会共享缓冲区的数据,这可能导致输出结果与预期不符。

所以用户缓冲区的类型有三种,分别是:

(1)全缓冲:缓冲区填满时刷新(如普通文件)。
(2)行缓冲:遇到换行符\n时刷新(如终端标准输出stdout)。
(3)无缓冲:立即输出(如标准错误stderr)。

用户缓冲区和内核缓冲区的关系:

用户缓冲区与内核缓冲区(如页缓存Page Cache)是独立但协作的两层:用户缓冲区位于进程地址空间,由应用程序或标准库管理。而内核缓冲区位于内核空间,用于缓存磁盘数据或网络数据,减少物理I/O。

数据流示例:

复制代码
应用程序数据 → 用户缓冲区 → write()系统调用 → 内核缓冲区 → 磁盘/网络

用户缓冲区与内核缓冲区区别:

用户缓冲区刷新(如fflush())仅将数据复制到内核缓冲区,不保证落盘。内核缓冲区由内核管理,通过fsync()或定时刷新(通常30秒)写入磁盘。

缓冲区的控制方法:

(1) 标准库缓冲控制

setvbuf():设置缓冲区模式(全缓冲/行缓冲/无缓冲)及自定义缓冲区。

fflush():强制刷新指定文件的用户缓冲区到内核。

setbuf()/setbuffer():简化版缓冲区设置。

(2) 系统调用绕开用户缓冲区

使用read()/write()等系统调用时,数据直接在内核和用户空间传递,不经过标准库缓冲区(但仍有内核缓冲区参与)。

(3) 强制落盘

fsync(fd):确保内核缓冲区数据写入物理磁盘。

fdatasync(fd):类似fsync,但只刷新数据部分(不更新元数据)。

用户缓冲区的核心作用

减少系统调用开销 :每次系统调用(如read()/write())都需要从用户态切换到内核态,涉及上下文保存、权限检查等开销。通过缓冲区累积数据后批量操作,可大幅降低切换频率。(示例 :若每次写1字节,调用write()100次需100次系统调用;而用1KB缓冲区累积数据后写入,仅需1次系统调用。)

适配不同I/O粒度:应用程序的数据处理单位(如逐字符)可能与内核或磁盘的块大小(如4KB)不匹配。缓冲区作为中间层,可累积小数据到合适粒度再提交。

优化硬件访问:磁盘或网络设备更适合大块数据传输。缓冲区积累足够数据后,内核可合并多次小写入为单次大块I/O,提升设备利用率。

相关推荐
Loving_enjoy28 分钟前
DFT可测试性设计规则与检查:确保芯片可测试性的关键步骤
学习
ylscode34 分钟前
CVE-2026-31694 漏洞深度分析:Linux 内核 FUSE 组件存在本地提权风险,普通用户可直取 root 权限
linux·运维·服务器
r_oo_ki_e_38 分钟前
Java反射机制学习笔记
java·笔记·学习
Nontee1 小时前
数据类型与包装类 — 一个新手学Java的数据类型笔记
java·笔记·python
ysa0510301 小时前
【板子】树上启发式合并
数据结构·c++·笔记·算法
hengcaib1 小时前
金税四期下盐城企业财税合规技术路径:代理记账选型的技术思维
笔记
无足鸟ICT2 小时前
【RHCA+】bash命令
linux·开发语言·bash
weixin_307779132 小时前
Linux下Docker Compose里运行的MySQL数据库故障诊断Shell脚本
linux·运维·mysql·docker·自动化
小生不才yz2 小时前
Shell脚本精读 · S14-02 | 脚本模板:从 20 行工具到可维护项目
linux
x-cmd2 小时前
Linus 9 年前说「模糊测试有效」——今天已成 OSS-Fuzz 时代铁律
linux·ai·rust·开源·自动化·agent·安全性测试