Linux操作系统学习(文件缓冲区)

news2025/1/12 1:37:48

文章目录

  • 缓冲区
  • fork后的缓冲区

缓冲区

什么是缓冲区?

​ 缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区。

缓冲区分为内核缓冲区和用户缓冲区

​ 内核缓冲区是网络传输、文件io等等的“中转”,由操作系统控制,是不可见的,用户必须使用系统提供的接口才能使用到,所以说操作系统不相信任何人,只提供相关接口(read、write等)。

​ 一般每个语言都给用户提供了缓冲区,这里以C语言来举例

​ 在使用C语言的printf函数时,默认是向stdout写入的,那么下面做几个测试:

测试1:stdout的类别是显示器

可以看出,没有\n 打印的hello不会及时向显示器输出,而是最后return时才显示。

测试2:stdout的类别是磁盘文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XsLbTPut-1677869141834)(G:\Typora\图片保存\image-20221208195005918.png)]

可以看出,关闭test,5行hello并没有写入到文件,而不关闭fd 却写入文件里了

首先要知道,stdout的类型是FILE*,FILE是C语言提供的,FILE是一个结构体只不过typedef了。

FILE结构体包括了很多数据,其中就有 缓冲区,以及fd=1.

  • 因为是c语言提供的FILE,所以这个缓冲区属于C语言缓冲区
  • stdout代表显示器,固定去找struct file* array[]中1的位置

测试1和测试2的fprintf是C接口,他们输出的信息都会先缓存到C的缓存区也就是用户缓存区。

测试1没关闭1,此时1的类别属于显示器,那么他就是向显示器输出

  • 当我们在函数结尾没加\n时,它不刷新(注意,man函数的return会刷新缓存,所以最后结束时他会刷新一下)
  • 当我们加了\n时,他就会刷新缓冲区

测试1的fd1表示显示器,向显示器输出的刷新策略是行缓存:换行是刷新缓冲区;

测试2关闭1,之后在代开test.txt文件,根据文件描述符的分配规则,此时1的类别属于磁盘文件,那么就是向文件输出

  • 关闭fd时,向文件输出的字符没有被写入,在结束进程时会刷新缓冲区,但是提前关闭fd就等于“没路了”
  • 未关fd时,反而写入文件中了

测试2的fd1表示磁盘文件,向磁盘文件输出的刷新策略是全缓存:全部缓存区满了才会刷新

​ 最终C语言的缓冲区会通过系统调用接口刷新到文件内核缓冲区,通过文件内核缓冲区刷新到外设(磁盘、显示器等等),而测试2中close(fd)等于是提前把test.txt的fd切断了,C缓冲区无法与文件内核缓冲区建立联系,最后数据就留在了缓冲区

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Zvh9hst-1677869141835)(G:\Typora\图片保存\image-20221208205936953.png)]

注意:内核将缓冲区中的数据“写”到标准输入磁盘文件里,这里“写”不是将缓冲区中的数据移动到磁盘文件里,而是复制到磁盘文件里,也就说此时磁盘文件里保留了一份缓冲区内容的备份

综上,缓冲刷新策略有以下三种:

  • 行缓冲(如向显示器刷新)
  • 全缓冲(如向磁盘文件刷新)
  • 无缓冲(直接写入)

对于测试1和测试2中,可以用fflush(),强制刷新

假如没有缓冲区,我们要从磁盘中读取数据,有几个字符,CPU就要读写几次,CPU是高速率的

例如让打印机打印某个文本,打印机是低速的,CPU是高速的,将数据放入缓冲区,就进行其他的工作了

fork后的缓冲区

假如我们利用fork创建一个子进程,那么子进程的缓冲区是什么样的?

测试:

把输出重定向到文件里,当目标文件发生变化时,操作系统和C语言会自动调整刷新策略

我们知道:

  • 先fork在执行代码,子进程和父进程共享同一份,等于打印两份
  • 先执行代码再fork,本应该不会打印两份,而实际上除了系统接口write的写入(write写到内核缓冲区,由OS刷新到外设中),全都执行了两份

原因:

​ 重定向到文件时,刷新策略变为全缓冲,而父进程的C的缓冲区属于代码数据,是FILE结构体里的一部分,所以要被共享。可是进程在退出时会把用户缓冲区的数据刷新到系统(进程对数据进行写入),父子进程谁先写入谁就会先发生写时拷贝(只要有一个进程刷新用户缓冲区就代表代码数据发生改变),于是子和父进程就各有一份

解决这个问题,我们可以在 fork 前调用 fflush(stdout) 函数强制把父进程缓冲区的数据刷新到系统。
行写入),父子进程谁先写入谁就会先发生写时拷贝(只要有一个进程刷新用户缓冲区就代表代码数据发生改变),于是子和父进程就各有一份

解决这个问题,我们可以在 fork 前调用 fflush(stdout) 函数强制把父进程缓冲区的数据刷新到系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/388353.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】P2 vi/vim 编辑器

vim编辑器vim 编辑器介绍vim 三种工作模式vi/vim 操作打开/创建文件命令模式快捷指令底线模式快捷指令前言 上节内容: Linux 基本命令 链接: https://blog.csdn.net/weixin_43098506/article/details/129298221 本节内容: Linux vi 编辑器。 …

STM32 10个工程篇:1.IAP远程升级(一)

清晨一大早起来开始撰写STM32 10个例程篇的第一章即串口IAP远程升级,虽然网络上有很多免费和付费的STM32教程,但是仍然不断地说服自己沉住气、静下心写一份独一无二的,这份独一无二中也凝聚了一名MCU工程师5年间不断地项目迭代积累&#xff0…

总结磁共振成像的脑龄预测的人工智能模型

脑龄预测的人工智能模型 介绍基于神经影像的BA预测BA预测建模:从统计方法到DL统计方法使用统计/最大似然估计方法的BA研究的主要结果深度学习使用DL方法进行BA研究的主要结果可解释的人工智能(即可解释的深度学习方案)可解释的能力(Interpretability,)、可因果性和可解释性…

剑指 Offer —— 数组和字符串

文章目录剑指 Offer 04. 二维数组中的查找代码实现解题方案 思路算法步骤剑指 Offer 05. 替换空格题目描述代码实现解题方案 思路算法步骤剑指 Offer 11. 旋转数组的最小数字 - 解决方案题目描述代码实现剑指 Offer 04. 二维数组中的查找 在一个 n * m 的二维数组中&#xf…

csdn写文章自定义表格怎么做

前言 CSDN写文章时,经常会用到表格,不同于Word文档中直接插入表格(自定义几行几列),使用CSDN自带的md文本编辑器时,很难快速插入想要的表格样式,追究原因,也是因为md的语法问题&…

C语言刷题(4)——“C”

各位CSDN的uu们你们好呀,今天小雅兰的内容又到了我们的复习啦,那么还是刷题噢,话不多说,让我们进入C语言的世界吧 BC55 简单计算器 BC56 线段图案 BC57 正方形图案 BC58 直角三角形图案 BC59 翻转直角三角形图案 BC60 带空格…

Python计算分类问题的评价指标(准确率、精确度、召回率和F1值,Kappa指标)

机器学习的分类问题常用评论指标有:准确率、精确度、召回率和F1值,还有kappa指标 。 每次调包去找他们的计算代码很麻烦,所以这里一次性定义一个函数,直接计算所有的评价指标。 每次输入预测值和真实值就可以得到上面的指标值&a…

Camtasia2023电脑屏幕录像视频编辑录屏软件

Camtasia是一款专业的录屏软件,由TechSmith开发。它旨在帮助用户创建高质量的视频内容,包括演示、培训视频、演讲录像、教程等等。 Camtasia适合于需要制作视频教程、软件演示、游戏录像等内容的个人和企业用户。例如,软件开发人员可以使用它…

JUC并发编程与源码分析笔记10-聊聊ThreadLocal

ThreadLocal简介 恶心的大厂面试题 ThreadLocal中ThreadLocalMap的数据结构和关系ThreadLocal的key是弱引用,这是为什么ThreadLocal内存泄漏问题你知道吗ThreadLocal中最后为什么要加remove方法 是什么 ThreadLocal提供线程局部变量。这些变量与正常的变量不同&…

基于神经辐射场(Neural Radiance Fileds, NeRF)的三维重建- 简介(1)

Nerf简介 Nerf(neural Radiance Fileds) 为2020年ICCV上提出的一个基于隐式表达的三维重建方法,使用2D的 Posed Imageds 来生成(表达)复杂的三维场景。现在越来越多的研究人员开始关注这个潜力巨大的领域,也…

十大排序(C++版)

测试排序的题目&#xff1a; 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 堕落的做法&#xff1a; class Solution { public:vector<int> sortArray(vector<int>& nums) {sort(nums.begin(),nums.end());return nums;} };视频推荐&#xff1a; …

洛谷:P1554 梦中的统计 JAVA

思路&#xff1a;定义一个长度为10的数组&#xff0c;数组下标代表数组元素的数字&#xff0c;比如arr[0]代表数字0.用一个for循环&#xff0c;对每个数先取余再取整&#xff0c;知道取整得到的数为0&#xff0c;说明该数字已经被拆解完了。今天又学了一个输入&#xff0c;原来…

2020蓝桥杯真题美丽的2(填空题) C语言/C++

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝特别喜欢 2&#xff0c;今年是公元 2020 年&#xff0c;他特别高兴。 他很好奇&#xff0c;在公元 1 年到公元 2020 年&#xff08;包含&#xff09;中&#xff…

论文投稿指南——中文核心期刊推荐(电影、电视艺术)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

73. python第三方库安装教程(超详细)

73. python第三方库安装教程&#xff08;超详细&#xff09; 文章目录73. python第三方库安装教程&#xff08;超详细&#xff09;1.知识回顾2. openpyxl 库的作用3. 第三方库的安装步骤【警告内容释义】4. 更新pip5. pip 常用命令1. 什么是pip2. pip --version 查看 pip 版本和…

车载雷达实战之Firmware内存优化

内存&#xff08;Memory&#xff09;是计算机中最重要的部件之一&#xff0c;计算机运时的程序以及数据都依赖它进行存储。内存主要分为随机存储器&#xff08;RAM&#xff09;,只读存储器&#xff08;ROM&#xff09;以及高速缓存&#xff08;Cache&#xff09;。仅仅雷达的原…

树莓派Pico W无线WiFi开发板使用方法及MicroPython编程实践

树莓派Pico W开发板是树莓派基金会于2022年6月底推出的一款无线WiFi开发板&#xff0c;它支持C/C和MicroPython编程。本文介绍树莓派Pico W无线WiFi开发板的使用方法及MicroPython编程示例&#xff0c;包括树莓派Pico W开发板板载LED使用及控制编程示例&#xff0c;Pico W开发板…

Spring——什么是IOC?

一、原则高内聚、低耦合二、什么是IOC&#xff1f;控制反转&#xff0c;把对象创建和对象之间的调用过程&#xff0c;交给spring进行管理三、使用IOC的目的是什么&#xff1f;降低耦合&#xff08;谁和谁的耦合&#xff1f;&#xff1f;如何降低的&#xff1f;&#xff09;原来…

openai-chatGPT的API调用异常处理

因为目前openai对地区限制的原因&#xff0c;即使设置了全局代理使用API调用时&#xff0c;还是会出现科学上网代理的错误问题。openai库 0.26.5【错误提示】&#xff1a;raise error.APIConnectionError(openai.error.APIConnectionError: Error communicating with OpenAI: …

泛型详解.

1 泛型的引入 问题&#xff1a;我们之前实现过的顺序表&#xff0c;只能保存 int 类型的元素&#xff0c;如果现在需要保存 指向 Person 类型对象的引用的顺序表&#xff0c;请问应该如何解决&#xff1f;如果又需要保存指向 Book 对象类型的引用呢&#xff1f; 之前写的顺序表…