【Linux系统编程十六】:(基础IO3)--用户级缓冲区

news2024/11/27 11:12:53

【Linux系统编程十六】:基础IO3--用户级缓冲区

  • 一.用户级缓冲区
  • 二.缓冲区刷新策略
    • 1.验证:
  • 三.缓冲区意义

一.用户级缓冲区

在这里插入图片描述
我们首先理解上面的代码,分别使用printf和fprintf,fwrite往1号文件描述符里输出,也就是往显示器上输出,然后输出完后,就将显示器文件关闭。

我们将发现最后什么都不会输出,这是为什么呢?
printf,fprintf,fwrite里不是封装了系统调用接口write吗?它不是将内容输出到显示器上了吗?为什么显示器上不显示呢?

因为我们输出的内容并没有到显示器上,而是放在了一个叫缓冲区的地方。
并且这个缓冲区绝不在内核里。为什么呢?如果这个缓冲区在内核里,那么只要当内容放进缓冲区里,最后程序结束肯定会刷新出来,而这里并没有刷新出来,说明这个缓存区不是内核里的缓冲区。那这个缓冲区是什么呢?

其实这个缓存区是在内核外面,是属于用户级别的缓冲区,它是C语言给我提供的缓冲区!

1.我们输出的内容首先会存放在C语言提供的缓冲区里,当有合适条件时,就会调用wirte接口将内容刷新写入到内核里。
在这里插入图片描述
2.而这个合适的条件就是指缓冲区的刷新策略,比如显示器文件当遇到\n时就会将当前和之前的内容全部刷新出去:刷新的本质就是调用wirte将内容写入到内核里:
在这里插入图片描述
3.所以这也验证了exit和_exit的区别:exit在退出之前会刷新缓冲区。而_exit在退出之前不会刷新缓冲区。不是_exit不想刷,而是_exit它是系统调用接口,在内核里面,而我们所说的缓冲区在内核外面,它怎么刷新呢?所以exit作为库函数封装了_exit,并且在调用_exit之前,肯定调用了fflush接口,刷新了缓冲区。
在这里插入图片描述

所以:目前在我们所学习中,只需要考虑用户级缓冲区,而不是内核里的缓冲区,内核里的缓冲区有操作系统来刷新。
在这里插入图片描述

二.缓冲区刷新策略

目前我们认为,只要将数据刷新到内核里面,数据就可以被硬件获取。中间的过程不要关心,由操作系统来解决。但是我们要理解缓冲区是如何刷新的,刷新策略有哪些:

缓冲区刷新问题:
1.无缓冲:直接刷新。
2.行缓冲:遇到\n就刷新,没有遇到就不刷新。—显示器文件刷新策略
3.全缓冲:缓冲区满了才刷新。—普通文件刷新策略
4.特殊:当进程退出时,也会刷新缓冲区。

在这里插入图片描述
【问题】缓冲区在哪里呢?
缓冲区在FILE结构体里:
FILE里除了封装了文件描述符,还有对应打开文件的缓冲区字段和维护信息:在这里插入图片描述

所以对应缓冲区,我们就可以看作是在用户层malloc申请的一块资源空间。

1.验证:

在这里插入图片描述
这里前三个调用库函数,最后一个调用系统调用write接口。最后再使用fork函数。
往显示器里输出:
显示器文件采取的刷新策略是行刷新,所以遇到换行,就会将缓冲区内容刷新。
过程也很简单:首先将要输入的内容放入缓冲区,如果有合适的条件就会调用write接口将数据写入到内核里:
在这里插入图片描述

fork创建的子进程,创建完后,后面也没有代码,就退出了。
而我们如果改成下面的操作就会发生不同的效果:
在这里插入图片描述
当我们将输出的内容重定向到log.txt文件时,再打印log.txt内容却发现打印了7条语句!这是为什么呢?

1.肯定和fork有关/肯定跟重定向有关
2.重定向后,就是往普通文件输出了,而不是往显示器文件里输出。所以缓冲区刷新策略就发生改变。
3.普通文件的刷新策略是全缓冲,也就是当缓冲区满了再刷新。
4.我们要理解缓冲区是用户级的,可以看成进程申请malloc的一块资源。
5.当我们从缓冲区内容刷新到操作系统里时,这个过程就相当于是写入数据了,而往父进程里写入数据,会发生写时拷贝,会将缓冲区拷贝一份给子进程。而当子进程创建出来后没有代码可用,就退出了,父进程也退出了。但要注意进程退出之前会将缓冲区的内容刷新,所以最后会将刷新两个一个的缓冲区内容到内核里。
6.witre是系统调用接口,直接就将数据写入到操作系统里,不会放入到缓冲区里。
在这里插入图片描述
在这里插入图片描述

根据以上的理解,我们就知道为什么第一个出现的是系统调用write输出的内容了,因为重定向后变成全缓冲,前面的三个库函数接口走完缓冲区里的内容还是不会刷新,要等缓冲区满了才会刷新,而系统调用直接就写入到内核里了。
并且也能理解为什么库函数的输出的内容输出了两次,因为重定向导致刷新策略改变和写时拷贝的发生。

三.缓冲区意义

缓冲区的存在可以解决用户效率的效率问题,可以赞上多个数据然后统一刷新,让我们的C语言接口变得更快。因为有些数据只是拷贝到缓冲区里,但并没有真正的写入操作系统,拷贝完后,后面的操作就跳过返回了。
还有一个作用那就是【配合格式化输出!没有缓冲区,C语言是无法完成格式化的输出的,需要有缓冲区来配合实现。

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

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

相关文章

论文阅读——InternImage(cvpr2023)

arxiv:https://arxiv.org/abs/2211.05778 github:https://github.com/OpenGVLab/InternImage 一、介绍 大部分大模型都是基于transformer的,本文是一个基于CNN的视觉基础模型。使用可变性卷积deformable convolution作为核心操作&…

docker复制镜像文件

一、复制镜像 #1. 查找本机已有的镜像docker images |grep xxxx#2. 将镜像复制出来指向到xxxx.tar的文件中 docker save 343cca04e31d > xxxx.tareg: 二、加载镜像 直接将拷贝好的镜像包直接加载即可 docker load < myimage.tar

【C++】一文简练总结【多态】及其底层原理&具体应用(21)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.多态的概念二.多态的实现1&#xff…

Codeforces Round 908 (Div. 2)视频详解

Educational Codeforces Round 157 &#xff08;A--D&#xff09;视频详解 视频链接A题代码B题代码C题代码D题代码 视频链接 Codeforces Round 908 (Div. 2)视频详解 A题代码 #include<bits/stdc.h> #define endl \n #define deb(x) cout << #x << "…

mac M2 anaconda 解决装不了python3.7

今天发现一个很奇怪的问题 但是我一换成 conda create -n DCA python3.8.12就是成功的 这个就很奇怪, 解决如下 https://towardsdatascience.com/how-to-manage-conda-environments-on-an-apple-silicon-m1-mac-1e29cb3bad12 998 conda search pythonconda search python …

C++之函数中实现类与调用总结(二百五十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

SpringMVC使用AOP监听方法推送数据

导入aop的maven依赖 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.12</version> </dependency>创建一个spring的XML文件编写aop配置 <?xml version"1.0" …

基于springboot的二次元商品销售网站的设计与开发

大家好我是玥沐春风&#xff0c;今天分享一个基于springboot的二次元商品销售网站的设计与开发&#xff0c;项目源码以及部署相关请联系我&#xff0c;文末附上联系信息 。 开发工具及技术 2.3.1 Spring Boot框架 SpringBoot是一个全新的开源的轻量级框架。简化了Spring应用的…

Linux中的权限

目录 一、shell命令以及运行原理 二、Linux权限的概念 三、权限的八进制表示 四、修改文件的拥有者和所属组 五、权限常见的问题 1、目录的权限 2、umask 3、粘滞位 一、shell命令以及运行原理 首先&#xff0c;我们先来看看这个问题&#xff1a;我们使用命令是直接操…

electron安装报错:Electron failed to install correctly...解决方案

问题描述&#xff1a; 按照官方文档在yarn dev时报错&#xff1a; 一般遇到Electron failed to install correctly&#xff0c;please delete node_moules/electron and try installing again这种错误时&#xff0c;就是electron本体没有下载成功 解决方案&#xff1a; 1、…

GaN HEMT 电容的分析建模,包括寄生元件

标题&#xff1a;Analytical Modeling of Capacitances for GaN HEMTs, Including Parasitic Components 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;14年&#xff09; 摘要&#xff1a;本文提出了一种基于表面势的终端电荷和电容模型&#xff0c;包…

Android 10.0 系统默认打开OEM解锁开关功能实现

1.前言 在10.0的系统定制中,在9.0系统以后为了设备的安装,系统开始启用oem机制,所以在adb push文件就需要先oem解锁,然后才可以 进行相关操作,所以就需要默认打开oem解锁的开关,来方便oem解锁功能的实现 如图: 2.系统默认打开OEM解锁开关功能实现的核心类 packages\ap…

【计算机网络笔记】网络层服务模型——虚电路网络

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

【C++数据结构】线性表的本质和概念

文章目录 前言一、线性表的定义1.1 线性表的定义1.2 线性表的表现形式1.3 线性表 ( List ) 的抽象定义1.4 线性表的性质1.5 简单解释 二、生活中的线性表三、抽象实现线性表List3.1 线性表的本质和操作3.2 抽象实现 总结 前言 在计算机科学与数据结构领域&#xff0c;线性表是…

使用comicai绘制漫画

在bard中输入提示语&#xff1a; 再写一个关于校园爱情的漫画脚本&#xff0c;里面的角色要求都是人类&#xff0c;没有动物&#xff0c;简短&#xff0c;用英文 填写漫画标题和作者&#xff1a; 将bard生成的脚本如何框中&#xff1a; 选择并生成角色形象&#xff08;通过提示…

Docsify 和 Hugo 之间的选型

对文档的编译&#xff0c;目前的发布方案是越来越注重 MD 的编辑和发布。 针对其他 Wiki 的选择&#xff0c;MD 文件的编辑通常会保留修改记录&#xff0c;同时不依赖中央数据库和其他类型的 Web 应用服务。 随着各大云平台的支持&#xff0c;包括 GitHub Page 和 Google 的 …

时序预测 | MATLAB实现WOA-CNN-LSTM-Attention时间序列预测(SE注意力机制)

时序预测 | MATLAB实现WOA-CNN-LSTM-Attention时间序列预测&#xff08;SE注意力机制&#xff09; 目录 时序预测 | MATLAB实现WOA-CNN-LSTM-Attention时间序列预测&#xff08;SE注意力机制&#xff09;预测效果基本描述模型描述程序设计参考资料 预测效果 基本描述 1.MATLAB实…

AI:72-基于深度学习的火灾检测

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

【LeetCode刷题笔记】栈和队列

456. 132 模式 解题思路: 1. 单调递减栈,栈中存放的值当作 k 值,从右往左遍历数组,对于遇到的每一个元素 j 找最大的 k,遇到 nums[j] > 栈顶</

mysql explain type 枚举

explain 查看 sql 查询是否走索引。 其中 type 的枚举如下 类型说明system表只有一行&#xff08;系统表&#xff09;&#xff0c;这是 const 类型的特例const单表中的某个固定的值eq_ref使用唯一索引等值查找一个行ref使用非唯一索引查找所有匹配某个单个值的行fulltext使用…