当前位置: 首页 > news >正文

【Linux】:用户缓冲区

1.前言(引出现象)

我们看一段代码,

我们运行这段代码, 

再次运行,并将打印结果重定向到文件log.txt中, 结果除了系统调用write的输出,其余输出都多打印一次。这是为什么呢?我们先了解几个知识点,再来回答这个问题。

2. C语言标准I/O函数的原理

通常,使用标准I/O的第一步是调用fopen()打开文件。

  • fopen()函数不仅会打开文件,还会创建一个缓冲区(在读写模式下会创建两个缓冲区)以及一个包含文件和缓冲区数据的结构。
  • 另外,fopen()返回一个指向该结构的指针,以便其他函数知道如何找到该结构。
  • 假设把该指针赋给一个指针变量fp,我们就说fopen()函数“打开一个流”。如果以文本模式打开该文件,就会获得一个文本流;如果以二进制模式打开文件就会获得一个二进制流。

这个结构通常包含一个指定流中当前位置的文件指示器、包含错误和文件结尾的指示器、一个指向缓冲区开始处的指针、一个文件标识符和一个计数(统计实际拷贝进缓冲区的字节数)。
一般调用这些函数,文件中的缓冲大小数据块就被拷贝到缓冲区中,缓冲区的大小引实现而异。

在初始化结构和缓冲区后,输入函数按照要求从缓冲区中读取数据,当它读取数据时,文件位置指示器被设置为指向刚读取字符的下一个字符。由于stdio.h系列的所有输入函数共用一个缓冲区,所以调用任何一个函数都将从上一次函数停止调用的位置开始。

摘抄自:《C Primer Plus》

3.缓冲区

C语言中FILE是结构体,文件类型的指针 - ostartech - 博客园 (cnblogs.com)

【Linux】分析缓冲区,刷新机制,FILE_内核模块 刷新缓冲-CSDN博客

深究标准IO的缓存 - orlion - 博客园 (cnblogs.com)

Linux 系统调用 —— fork 内核源码剖析 - 陈心朔 - 博客园 (cnblogs.com)

解释现象:

第一次程序运行,我们并没有重定向,输出的目标文件都是显示器,而显示器一般采用行缓冲策略,所以当输入换行符到缓冲区时,库函数才会调用系统接口,将用户层的缓冲区数据拷贝到内核层缓冲区。

第二次的程序运行,我们将输出的内容重定向到普通文件,普通文件的缓冲区一般采用全缓冲策略,要将缓冲区填满才会刷新缓冲区,由于printf、fprintf和fwrite输出的数据较小,不足以填满缓冲区,所以此时缓冲区的刷新是通过调用return,return调用exit刷新的。而在调用人return前,我们创建了一个子进程,子进程会继承父进程的数据和代码,为刷新的缓冲区也被继承了。所以库函数输出的内容重复了两次。      系统调用write输出的内容只打印一次,内核的缓冲区刷新机制我们暂且不讨论。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 更新RK3588开发板的rknn_server和librknnrt.so【这篇文章是RKNPU2从入门到实践 --- 【5】的配套文章】
  • js发送邮件:如何在Node.js实现邮件发送?
  • vue 批量导出pdf 压缩包 zip
  • Location-Aware Self-Supervised Transformers for Semantic Segmentation
  • 最新保姆级教程
  • 车窗边缘上的装饰边和花点的作用
  • 废品回收小程序,从传统到现代化的回收模式
  • spring cloud与boot与cloud alibaba版本对应
  • AR 眼镜之-系统通知定制(通知弹窗)-实现方案
  • 我在IBM的时光碎片1 - 回忆昊海大厦
  • Unity (编辑器)数据持久化 之 ScriptableObject初识与创建
  • Adobe Illustrator vs Photoshop:设计界的“相声搭档”
  • 【类模板】模板参数的推断
  • [激光原理与应用-126]:傅里叶变化与频域分析
  • Redis的内存淘汰策略-volatile-ttl
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • docker python 配置
  • exif信息对照
  • JavaScript创建对象的四种方式
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • PHP那些事儿
  • Vue官网教程学习过程中值得记录的一些事情
  • 基于组件的设计工作流与界面抽象
  • 前言-如何学习区块链
  • No resource identifier found for attribute,RxJava之zip操作符
  • kubernetes资源对象--ingress
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (2024)docker-compose实战 (9)部署多项目环境(LAMP+react+vue+redis+mysql+nginx)
  • (3)STL算法之搜索
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (算法)前K大的和
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!
  • (一)Docker基本介绍
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • **PHP分步表单提交思路(分页表单提交)
  • .form文件_SSM框架文件上传篇
  • .net Application的目录
  • .net core Swagger 过滤部分Api
  • .Net MVC4 上传大文件,并保存表单
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • @ResponseBody
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)