用户缓冲区概念

文章探讨了C库中的printf和fwrite等函数如何通过用户级和系统级缓冲区工作,解释了为何write可以直接打印而库函数需要额外刷新。作者还揭示了缓冲区的存在解决了效率问题并配合格式化功能,以及用户级缓冲区在fork后的行为模拟。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看现象,printf / fprintf / fwrite 一定封装了write , 但是执行代码看到大家都是去掉\n 和close(1),库函数无法打印,write可以
你不是说的库函数封装了write,怎么打印不出来?
在这里插入图片描述
在这里插入图片描述

如果执行这两句代码你会发现程序会等待一会最后结束时打印出来,这是因为缓冲区的存在,printf把数据写入到缓冲区里面了
则printf fprintf fwrite 也一定会将数据写入进缓冲区,只不过这个缓冲区绝对不是系统级缓冲区(文件缓冲区)

为什么系统接口write能打印?
write通过文件描述符找到文件struct file 找到缓冲区写入到系统级缓冲区中,close(1)时文件关闭时它自动刷新缓冲区到磁盘中或显示器
在这里插入图片描述
为什么C接口看不到?
主要原因还是因为这个缓冲区一定不再操作系统内部!不是系统级别的缓冲区!
C语言提供了一个语言级 用户级缓冲区,这些C接口把数据写入到用户级缓冲区,之后close(1)关闭了文件和缓冲区,它想刷新也没地方刷新
在这里插入图片描述

写入用户级缓冲区的字符如果带了\n,C标准库会识别到,则立即把数据刷新到操作系统缓冲区中。
c库在合适(\n or fflush)的时候才调用wirte接口把用户级缓冲区写入到系统缓冲区中(fflush内部也是wirte)
这种刷新叫用户刷新,刷新时利用write() + 文件描述符写入到内核

尝试再次理解 exit 和 _exit
在这里插入图片描述
exit(1)打印了
_exit没打印

在这里插入图片描述
exit是C库函数,它调用fflush(stdout)刷新用户级缓冲区再调用_exit
_exit根本就不知道还有个用户级缓冲区这回事,则它不会刷新直接终止进程

目前我们认为,只要将数据刷新到了内核,数据就可以到硬件了

操作系统的缓冲区我们先不管
先来看看用户级缓冲区的刷新策略
1.写透 直接刷新
2.向显示器写是给人看的,那不就一行一刷新吗
3.向文件写入不需要每次都看一看,为了效率等缓冲区满了一气刷新
在这里插入图片描述
这个策略决定了什么时候调write把数据写入os中,fflush一定封装了write
在这里插入图片描述
问题:为什么要有这个缓冲区呢?
1、解决效率问题 ---- 用户的效率问题
这个缓冲区就像楼下的快递驿站一样,fprintf/fwrite不需要千里迢迢的去调用write,他只需要把数据放进缓冲区然后返回就这可以,如果没有缓冲区频繁调用系统接口也会有效率问题
就像快递公司希望我的件堆的满了再进行配送,那才效率高呢,而不是每次有数据每次都系统调用去送,那效率低。

最主要的解决你的效率问题,你不用自己坐飞机火车去西藏给人送键盘,你把东西放到驿站上楼就去打游戏就可以了。这就是为什么用C库输入输出接口很快

2、配合格式化
我们往显示器打印的是字符1 字符2 字符3 而不是数字123
你想打印数字%d a = 123 ,在调用write之前你得先把对应的数据格式化形成一个字符串给我写到一个区域里然后才能进行刷新

观察数据的流向
fprintf 会往缓冲区不断写入数据,再通过write往os里面写,写到os后C缓冲区的数据就会被清空
在这里插入图片描述

这个缓冲区在哪里???
文件操作绕不开,FILE,这是一个结构体
FILE- > fd
FILE里面还有对应打开文件的 缓冲区字段和维护信息
fprintf 把字符串往这个FILE* stdout 结构体中的缓冲区拷贝进入
在这里插入图片描述
如果我今天fopen打开了10个文件,那么我有几个用户级缓冲区?
10个!每个文件都有自己的缓冲区
那有几个文件描述符呢?10个!(即使打开的都是同一个文件)
因为你有个10个FILE* 指向的结构体嘛

这个FILE结构体属于用户呢?还是操作系统呢?
属于用户
这是缓冲区是不是属于用户级的缓冲区呢?
是的,在用户空间里(1~3)
在这里插入图片描述
在这里插入图片描述
C库在语言层malloc出的FILE结构体,里面有缓冲区

下面知道缓冲区属于malloc的一块堆空间的前提下,我们再来解决上面fork后出现奇怪打印问题
在这里插入图片描述
在这里插入图片描述

模拟实现一下 — C文件标准库 输入输出 <stdio.h>
https://gitee.com/ljh0617/linux_test/tree/master/11-7/file

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值