浅谈linux缓冲区的认识!

今天来为大家分享一波关于缓冲区的知识!那么既然我们要谈缓冲区,那么就得从是什么?为什么?有什么作用这几个方面来谈论一下缓冲区!然后再通过一些代码来更加深刻的理解缓冲区的知识!

引言:

是什么?

从最简单的理解方面来,我们可以将缓冲区理解成一块内存!那么这块内存是从哪里来的呢?在linux中一般我们所说的缓冲区都是由C提供的语言级别的缓冲区!

干什么的?

那么缓冲区的作用主要是用来干什么的呢?可以从我们生活中的例子来理解!假设你的朋友小张下个月就要过生日了,你要送他一个生日礼物!但是你们两个距离很远!一个在西藏,一个在海南!如果让你自行将生日礼物送给他,那么无疑将会浪费你的很多成本!但是现实中存在快递站,只需要你下楼将礼物交付给快递站,然后由快递站代替你送过去即可!那么在本例子内,快递站的作用就是一个缓冲区的作用!


为什么要存在缓冲区?

根据上面提到的例子,很容易理解,因为有了快递站的存在,使我们方便了很多!所以类似于此,缓冲区存在的意义就是为了提高效率,减少我们的成本!


下面通过一段代码来证明一下缓冲区确实存在!

我们用户通常写程序在屏幕上打印一段文字的时候!其中就利用到了缓冲区!例如下面这个例子!

运行这段程序之后,显示屏上并没没有立刻打印出“hello linux”,这是为什么呢?根据我们所了解到的知识,程序是自上向下运行的,运行到sleep的时候,printf语句一定是执行过了,但是为什么没有打印出结果呢?根据此例子可以充分的证明缓冲区的存在!!既然证明了缓冲区的存在,那么我们将来一步一步的进行分析缓冲区的相关知识1

那么从系统角度来将该如何理解的呢?

从操作系统角度上来看!用户输入一段指令,该指令并没有直接传递到内核文件内存中!而是将用户输入的指令存放到了C提供的语言级别的缓冲区内!然后在C语言的缓冲区中经过刷新之后!再传递到内核结构中的文件缓冲区中!最后系统会定期的将内存的数据刷新到磁盘中!此阶段也可以称之为刷新!在此,我们提到了两个缓冲区,一个是用户层的C语言提供的语言级别的缓冲区,一个是内核结构中的内核文件缓冲区!一般我们所考虑的都是C语言提供的语言级别的缓冲区!


缓冲区的一些特性:

根据缓冲区能够存储一定的数据可以推出:缓冲区一定存在着刷新的方式!

1.无缓冲(立即刷新!)

2.行缓冲(行刷新!)

一般对于显示器文件,都是基于行缓冲的模式!

3.全缓冲(存放满然后进行刷新!)

对于磁盘文件,都是基于全缓冲的方式!


那么根据以上的特征,缓冲区也会有着特殊的情况!

1.强制刷新!

2.进程退出后,会自动进行刷新!(无论是否满足刷新的条件!)


实例:充分理解缓冲区

下面通过一段代码来充分理解缓冲区中的行缓冲和全缓冲!

上面代码运行过后,每行代码都打印了出来!这是为什么呢?刚才不是还说是存在缓冲区的么?其实不难理解,因为每段代码都有了\n换行符,强制让缓冲区内的数据进行刷新!所以数据都原样的打印了出来!!

那么将上面的代码经过简单的修改就会出现另外一种结果!

经过上面代码简单的修改,我们发现C函数的调用都打印了两次,而是用系统调用的write确只调用了一次!这是为什么呢?其实很简单!

我们可以看出,我们将输出结果由原来的行缓冲转化成了全缓冲(因为将结果打印到了log.txt文本文件中,文本文档默认为全缓冲的刷新方式!)所以只有当将缓冲区填满的时候,才会进行刷新!才能打印到显示屏中!又因为调用了fork函数,创建了新的子进程!根据fork的特性会继承父进程的代码和数据块!因为此时代码仍然在缓冲区内!所以子进程也会继承这些相同的代码和数据块!然后当一个进程结束后,就会发生写时拷贝!这是因为当一个进程退出的时候,一般都会对缓冲区的数据进行刷新,那么算不算清空或写入的操作呢?答案是肯定的!当时算!所以就会发生写时拷贝!所以可以推出,一旦一个进程退出,那么就会发生写时拷贝!

根据上图结果看出,系统调用write只打印了一次!从这里可以推出:write没用使用C语言的缓冲区!因为C语言的一些函数,大多都是对系统调用的封装!大多都是因为封装的原因!而导致他们使用C提供的缓冲区!而系统调用处于内核级别,在用户级别的下面,直接将数据写入到内核文件系统中!所以不使用C提供的缓冲区!

实例中的主要知识点:

1.当我们直接向显示器打印的时候,显示器文件的刷新方式是行刷新!而是我们的代码输出的所有字符串,都有\n,fork之前,数据已经全部被刷新!包括systemcall!

2.重定向到log.txt之后,本质是向磁盘文件中写入(而不再是显示器里面!),我们系统对于数据的刷新方式已经由行刷新转化到了全刷新的方式!变成了全缓冲!

3.全缓冲意味着缓冲区变大,实际写入的简单数据,不足以将缓冲区填满!fork执行的时候,数据依然在缓冲区内部!

4.我们目前所谈的缓冲区,是和操作系统没有关系的!只能和C语言本身有关!!

5.C/C++提供的缓冲区,里面保存的一定是用户的数据!其属于当前进程运行的数据!但是如果当把数据交付给OS,这些数据就属于OS了,不再属于该进程了!

6.当进程退出的时候,一般会进行刷新缓冲区,即使我们的数据没有满足刷新条件!


证明缓冲区的存在以及其在内核中的结构!

既然我们都讲了这么多关于缓冲区的知识了,那么我们确实已经知道了缓冲区真实存在!那么能否让我看一看其到底是什么样子的呢?

通过以上函数,我们可以发现,大多的输入输出操作,以及文件的操作都用到了FILE该结构体!那么该结构体之中我们之前知道其包含了文件描述符fd,那么其是否介意再包含一个缓冲区的成员变量呢?答案是当然不介意的啦!

我们可以通过对FILE的观察来看一下缓冲区的真实存在!

我们通过grep指令来查看FILE的路径!然后在FILE内部继续进行查找,最后看到FILE内部有我们熟悉的文件描述符_fileno,以及我们今天所讲的缓冲区的内容!


至此,本文关于缓冲区的介绍到此为止,希望读完本篇文章,能对读者有一定的收获!

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

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

相关文章

【C++ Primer Plus学习记录】逻辑表达式

一、逻辑OR运算符:|| 如果表达式中的任何一个或全部都为true(或非零),则得到的表达式的值为true;否则,表达式的值为false。 ||的优先级比关系运算符低。 C规定,||运算符是个顺序点。即&#…

Navicat 技术指引 | 适用于 GaussDB 分布式的日志查询与配置设置

Navicat Premium(16.3.3 Windows 版或以上)正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能,还提供强大的高阶功能(如模型、结…

文献计量学方法与应用、主题确定、检索与数据采集、VOSviewer可视化绘图、Citespace可视化绘图、R语言文献计量学绘图分析

目录 一、文献计量学方法与应用简介 二、主题确定、检索与数据采集 三、VOSviewer可视化绘图 四、Citespace可视化绘图 五、R语言文献计量学绘图分析 六、论文写作 七、论文投稿 更多应用 文献计量学是指用数学和统计学的方法,定量地分析一切知识载体的交叉…

AWS攻略——使用中转网关(Transit Gateway)连接不同区域(Region)VPC

文章目录 Peering方案Transit Gateway方案环境准备创建Transit Gateway Peering Connection接受邀请修改中转网关路由修改被邀请方中转网关路由修改邀请方中转网关路由 测试修改Public子网路由 知识点参考资料 区别于 《AWS攻略——使用中转网关(Transit Gateway)连接同区域(R…

C++_函数重载

前言: 函数重载的意思就是可以有多个同名函数存在,但是这些同名函数的参数列表有着不同情形,以便区分。在C中,支持在同一作用域下可以声明、定义多个同名函数,但是这些函数的形参类型,类型顺序以及参数个数…

AI大规模专题报告:大规模语言模型从理论到实践

今天分享的AI系列深度研究报告:《AI大规模专题报告:大规模语言模型从理论到实践》。 (报告出品方:光大证券) 报告共计:25页 大规模语言模型基本概念 语言是人类与其他动物最重要的区别,而人类…

深入理解 Promise:前端异步编程的核心概念

深入理解 Promise:前端异步编程的核心概念 本文将帮助您深入理解 Promise,这是前端异步编程的核心概念。通过详细介绍 Promise 的工作原理、常见用法和实际示例,您将学会如何优雅地处理异步操作,并解决回调地狱问题。 异步编程和…

Linux的硬盘管理

本章主要介绍Linux磁盘管理 了解分区的概念对硬盘进行分区swap分区的管理 新的硬盘首先需要对其进行分区和格式化,下面来了解一下硬盘的结构,如图 硬盘的磁盘上有一个个圈,每两个圈组成一个磁道。从中间往外发射线,把每个磁道分…

信息系统工程的基本概念

系统是由相互作用和相互依赖的若干部分,按一定规律结合成的、具有特定功能的有机整体。系统有下述特性: (1)集合性。系统是由许多元素有机地组成的整体。每个元素服从整体,追求全局最优。 (2)相…

springboot3远程调用

RPC 两个服务器之间的调用 远程请求 内部服务之间的调用 可以通过 cloud 注册中心 openfeign等 外部服务的调用 http请求 外部协议 api:远程接口 sdk:本地调用 调用阿里云的天气请求

深度学习|词嵌入的演变

文本嵌入,也称为词嵌入,是文本数据的高维、密集向量表示,可以测量不同文本之间的语义和句法相似性。它们通常是通过在大量文本数据上训练 Word2Vec、GloVe 或 BERT 等机器学习模型来创建的。这些模型能够捕获单词和短语之间的复杂关系&#x…

要求CHATGPT高质量回答的艺术:提示工程技术的完整指南—第 27 章:如何避开和绕过所有人工智能内容检测器

要求CHATGPT高质量回答的艺术:提示工程技术的完整指南—第 27 章:如何避开和绕过所有人工智能内容检测器 使用高易错性和突发性方法 与人工智能生成的文本相比,人类写作往往具有更多的突发性,这是由于人类往往比人工智能生成的文…

【开源】基于Vue+SpringBoot的陕西非物质文化遗产网站

文末获取源码,项目编号: S 065 。 \color{red}{文末获取源码,项目编号:S065。} 文末获取源码,项目编号:S065。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 设计目标2.2 研究内容2.3 研究方法与…

GEE中Landsat中大改变——Landsat Collection 1 到 Collection 2 影像集合迁移

Landsat Collection 1 到 Collection 2 迁移 本指南提供了从Landsat Collection 1 数据切换 到 Collection 2 数据的说明。自 2022 年以来,集合 2 已在 Earth Engine 中完全可用, 自 2021 年 12 月 31 日以来,美国地质调查局 (USGS) 未生成集合 1 数据。Landsat Collection …

3D点云:平面模型上提取凸(凹)多边形方法

目录 一、实现原理 二、实现代码 三、运行结果 一、实现原理 首先要在点云中提取出潜在平面,对原始点云数据进行滤波,根据提取出的平面模型系数从滤波后的点云进行投影,然后根据投影后的点云计算其对应的二维凹(凸)多边形。 二、实现代码 #in

webrtc 设置不获取鼠标 启用回声消除

数 getDisplayMedia()(属于 navigator.mediaDevices 的一部分)与 getUserMedia() 类似,用于打开显示内容(或部分内容,如窗口)。返回的 MediaStream 与使用 getUserMedia() 时相同。 显示鼠标与否 getDisp…

案例064:基于微信小程序的考研论坛设计

文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…

正则表达式(7):转义符

正则表达式(7):正则表达式(5):转义符 本博文转载自 此处,我们来认识一个常用符号,它就是反斜杠 “\” 反斜杠有什么作用呢?先不着急解释,先来看个小例子。 …

【游戏引擎 - C#脚本系统】6、C#端调用C++函数

强烈建议阅读Mono官方文档 有mono库提供的API&#xff0c;这个过程非常简单&#xff0c;通过mono在C中注册函数&#xff0c;然后在C#中声明和调用这些函数 1、在C中注册Internal Call&#xff1a; C代码中定义一个函数 static void CppFunc() {std::cout << "这…

24 递归求解二叉树打家劫舍

问题描述&#xff1a;在上次大街万一条街道之后和一圈房屋后&#xff0c;小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为根。除了根之外&#xff0c;每栋房子有且只有一个父房子与之项链&#xff0c;一番侦查之后&#xff0c;聪明的小偷意识到…