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

用Linux的视角来理解缓冲区概念

缓冲区的认识

缓冲区(buffer)是存储数据的临时存储区域。当我们用C语言向文件中写入数据时,数据并不会直接的写到文件中,中途还经过了缓冲区,而我们需要对缓冲区的数据进行刷新,那么数据才算写到文件当中。而缓冲区通常是一块内存区域,可以是数组、队列、链表等数据结构。

代码举例

int main()
{//C接口FILE* fp=fopen("log.txt","w");//创建文件const char* buffer = "hello buffer\n"; fwrite(buffer,strlen(buffer),1,fp);//文件写入//系统接口close(fp->_fileno);return 0;
}

此时的数据其实就是写进了缓冲区中,但是我们此时的调用接口是不一样的,关闭文件调用的是系统调用接口,而且FILE结构体中是封装了文件描述符的。先认识后续会讲述原因。


其实我们是可以将我们缓冲区中的数据给刷新出来:

int main()
{FILE* fp=fopen("log.txt","w");const char* buffer = "hello buffer\n"; fwrite(buffer,strlen(buffer),1,fp);fflush(fp);//刷新缓冲区close(fp->_fileno);return 0;
}

 为什么要有缓冲区的存在

其实缓冲区的存在就是为了减少对数据的访问次数,当我们输入输出数据的时候,其实就是对文件信息进行交互的(一切皆文件)。我们为了避免每一次的文件访问IO操作,从而会降低效率,所以说可以建立一个像缓冲区这样的中转站,将数据与缓冲区交互,然后将所有的数据都接收处理好了以后再交给文件。

缓冲区的刷新方式

  1. 立即刷新(无缓冲)
  2. 行刷新(行缓冲)
  3. 缓冲区满了刷新(全缓冲)
  4. 强制刷新

一般对于显示器文件的刷新方式是行刷新(\n也是进行行刷新),而一般磁盘上的文件的刷新方式就是缓冲区满了再刷新。 我们也可以通过fflush函数强制的进行刷新缓冲区。而且进程退出后都会采取强制刷新,但是此时如果文件已经close的话(底层fd没了),数据依旧刷不进去的。


此时就可以浅浅的解释我们开始写的代码的,因为我们的一般文件的刷新策略是缓冲区满了才刷新的,这正是因为我们向log.txt这个文件里写的数据没有写满缓冲区,所以导致缓冲区没有刷新,从而该文件中并没有数据。其实如果你多写一些数据进去的话其实是可以写满的。

缓冲区与操作系统无关

 结论我们写代码时的缓冲区其实是属于C语言的,与操作系统并无关系。


int main()
{FILE* fp=fopen("log.txt","w");const char* buffer = "helllo buffer\n"; fwrite(buffer,strlen(buffer),1,fp);fclose(fp);//C语言接口return 0;
}

 该段代码的区别就是用了C语言接口关闭文件。而我们开头的那段代码是系统调用关闭文件。仅仅换了一种关闭方式就导致了文件中一个有数据一个没数据。所以说可以知道,C语言中的fclose其实是封装了系统调用的close,但是还多了一个步骤:刷新缓冲区。

也可以说明系统调用接口其实是没有缓冲区这个概念的,缓冲区其实是我们C语言库中后期封装好的。

 经典样例

代码一:

int main()
{printf("C:printf\n");fprintf(stdout,"C:fprintf\n");fputs("C:fputs\n",stdout);const char* arr = "system:write\n";write(1,arr,strlen(arr));return 0;
}


代码二:

int main()
{printf("C:printf\n");fprintf(stdout,"C:fprintf\n");fputs("C:fputs\n",stdout);const char* arr = "system:write\n";write(1,arr,strlen(arr));fork();//创建子进程return 0;
}


就上面的两段代码唯一的区别就是在程序结束之前是否创建了子进程。

现象就是:代码一没有创建子进程,而且就如我们意想的结果一样正常打印数据到log.txt文件当中,而代码二在打印结束的时候创建了子进程,最终log.txt文件中的数据打印了两份,除了系统调用write函数之外。

其实在我们./test.exe > log.txt 将本应该打印到显示器文件的数据重定向到log.txt文件当中时,就改变了缓冲区的刷新策略,从原先的行数新变成了缓冲区满了再刷新。所以在执行fork函数创建子进程之前的所有数据依旧还是存在缓冲区当中,而创建子进程后,父子进程代码共享,数据采用写时拷贝的方式存在着。当假设父进程先结束退出以后,此时父进程的缓冲区就会被强制刷新(也就是相当于清空缓冲区数据),而此时的子进程必然是会发生写时拷贝,数据独有一份,所以最终子进程退出时缓冲区的数据也会被强制刷新,所以最终数据就有两份了。

而针对于系统调用write函数并不是将数据写进缓冲区当中,而是直接写到操作系统中,因此以上操作就与该函数无关。

缓冲区在哪里  

我们知道缓冲区与操作系统无关,所以缓冲区在哪里呢,其实就在FILE的结构体中。

就那我们比较熟悉的函数fflush,该函数的作用是刷新缓冲区,而参数就是FILE*的文件指针,所以此时其实就可以看出端倪了。

FILE其实是一个结构体,我们前面知道FILE结构体当中封装了文件描述符,其实也有缓冲区,其实就是一些指针。


         

相关文章:

用Linux的视角来理解缓冲区概念

缓冲区的认识 缓冲区(buffer)是存储数据的临时存储区域。当我们用C语言向文件中写入数据时,数据并不会直接的写到文件中,中途还经过了缓冲区,而我们需要对缓冲区的数据进行刷新,那么数据才算写到文件当中。…...

C#中Enumerable.Range(Int32, Int32) 方法用于计算

目录 一、关于Enumerable.Range(Int32, Int32) 方法 1.定义 2.Enumerable.Range()用于数学计算的操作方法 3.实例1:显示整型数1~9的平方 4.实例2:显示整型数0~9 5.实例3:Enumerable.Range()vs for循环 &#x…...

Linux和windows进程同步与线程同步那些事儿(四):windows 下进程同步

Linux和windows进程同步与线程同步那些事儿(一) Linux和windows进程同步与线程同步那些事儿(二): windows线程同步详解示例 Linux和windows进程同步与线程同步那些事儿(三): Linux线…...

1. Logback介绍

Logback介绍 Logback旨在成为流行的log4j项目的继任者。它由Ceki Glc设计,他是log4j的创始人。它基于十年在设计工业级日志系统方 面的经验。结果产品,即logback,比所有现有的日志系统更快,具有更小的占用空间,有时差距…...

SqueezeNet:通过紧凑架构彻底改变深度学习

一、介绍 在深度学习领域,对效率和性能的追求往往会带来创新的架构。SqueezeNet 是神经网络设计的一项突破,体现了这种追求。本文深入研究了 SqueezeNet 的复杂性,探讨其独特的架构、设计背后的基本原理、应用及其对深度学习领域的影响。 在创…...

Python:正则表达式之re.group()用法

Python正则表达式之re.group()用法学习笔记 正则表达式是在处理字符串时非常有用的工具,而re.group()是在匹配到的文本中提取特定分组内容的方法之一。 1. re.group()的基本用法 在正则表达式中,通过圆括号可以创建一个或多个分组。re.group()用于获取…...

Shiro框架:Shiro登录认证流程源码解析

目录 1.用户登录认证流程 1.1 生成认证Token 1.2 用户登录认证 1.2.1 SecurityManager login流程解析 1.2.1.1 authenticate方法进行登录认证 1.2.1.1.1 单Realm认证 1.2.1.2 认证通过后创建登录用户对象 1.2.1.2.1 复制SubjectContext 1.2.1.2.2 对subjectContext设…...

WEB前端人机交互导论实验-实训2格式化文本、段落与列表

1.项目1 文本与段落标记的应用&#xff1a; A.题目要求: B.思路&#xff1a; &#xff08;1&#xff09;首先&#xff0c;HTML文档的基本结构是通过<html>...</html>标签包围的&#xff0c;包含了头部信息和页面主体内容。 &#xff08;2&#xff09;在头部信息…...

Python:list列表与tuple元组的区别

在Python中&#xff0c;List&#xff08;列表&#xff09; 和Tuple&#xff08;元组&#xff09; 都是用于存储一组有序元素的数据结构&#xff0c;但它们有一些关键的区别&#xff0c;包括可变性、性能、语法等方面。 1. List&#xff08;列表&#xff09; 用法&#xff1a;…...

如何基于 Gin 封装出属于自己 Web 框架?

思路 在基于 Gin 封装出属于自己的 Web 框架前&#xff0c;你需要先了解 Gin 的基本用法和设计理念。 然后&#xff0c;你可以通过以下步骤来封装自己的 Web 框架&#xff1a; 封装路由&#xff1a;Gin 的路由是通过 HTTP 方法和 URL 路径进行匹配的&#xff0c;你可以根据自己…...

VUE element-ui实现表格动态展示、动态删减列、动态排序、动态搜索条件配置、表单组件化。

1、实现效果 1.1、文件目录 1.2、说明 1、本组件支持列表的表头自定义配置&#xff0c;checkbox实现 2、本组件支持列表列排序&#xff0c;vuedraggable是拖拽插件&#xff0c;上图中字段管理里的拖拽效果 &#xff0c;需要的话请自行npm install 3、本组件支持查询条件动态…...

压测工具ab

Apache Benchmark(简称ab) 是Apache安装包中自带的压力测试工具 &#xff0c;简单易用, Apache的ab命令模拟多线程并发请求&#xff0c;测试服务器负载压力&#xff0c;也可以适用于其他服务&#xff1a;nginx、lighthttp、tomcat、IIS等其它Web服务器的压力 采用平台&#xf…...

P4学习(一) 环境搭建

系列文章目录 第一章 P4学习入门之虚拟机环境搭建 文章目录 系列文章目录前言一、P4是什么&#xff1f;二、搭建步骤1.下载虚拟机镜像2.虚拟机管理软件载入镜像2.1 找到你镜像的所在位置2.2 打开VMware Workstation2.3 载入镜像 3.检验环境是否配置成功 P4 的真机环境搭建 前言…...

openssl3.2 - 官方demo学习 - server-arg.c

文章目录 openssl3.2 - 官方demo学习 - server-arg.c概述笔记备注END openssl3.2 - 官方demo学习 - server-arg.c 概述 TLS服务器, 等客户端来连接; 如果客户端断开了, 通过释放bio来释放客户端socket, 然后继续通过bio读来aceept. 笔记 对于开源工程, 不可能有作者那么熟悉…...

Windows RPC运行时漏洞事后总结

2022年4月前后&#xff0c;Windows RPC运行时被曝出存在远程代码执行漏洞&#xff0c;当时曾引起很多人广泛关注。微软很快做出反应&#xff0c;发布补丁程序进行修补。这次事件中&#xff0c;Windows远程过程调用&#xff08;RPC&#xff09;运行时共出现三个关键漏洞&#xf…...

运算电路(1)——加法器

一、引言 微处理器是由一片或少数几片大规模集成电路组成的中央处理器。这些电路执行控制部件和算术逻辑部件的功能。微处理器能完成取指令、执行指令&#xff0c;以及与外界存储器和逻辑部件交换信息等操作&#xff0c;是微型计算机的运算控制部分。它可与存储器和外围电路芯片…...

ESP32-WIFI(Arduino)

ESP32-WIFI Wi-Fi是一种基于IEEE 802.11标准的无线局域网技术&#xff0c;是Wi-Fi联盟制造商的商标作为产品的品牌认证。它可以让电脑、手机、平板电脑等设备通过无线信号连接到互联网 。 在无线网络中&#xff0c;AP&#xff08;Access Point&#xff09;和 STA&#xff08;St…...

【网络虚拟化】网络设备常见冗余方式——堆叠、M-Lag、DRNI

网络设备常见冗余设计——堆叠、M-Lag、DRNI 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 网络设备常见冗余设计——堆叠、M-Lag、DRNI 网络设备常见冗余设计——堆叠、M-Lag、DRNI前言一、网络设备虚拟化二、堆叠技术1.技术原理2.…...

arm的侏罗纪二 cache学习

个人觉得inner shareable和outer shareable&#xff1b;POU和POC 是难点&#xff0c;慢慢学习吧。 inner shareable是cluster内 outer shareable是cluster之间 参考文献&#xff1a; 深入学习Cache系列 1: 带着几个疑问&#xff0c;从Cache的应用场景学起 https://www.eet-c…...

Protecting Intellectual Property of Deep NeuralNetworks with Watermarking

保护深度神经网络的知识产权与数字水印技术 ABSTRACT 深度学习是当今人工智能服务的关键组成部分&#xff0c;在视觉分析、语音识别、自然语言处理等多个任务方面表现出色&#xff0c;为人类提供了接近人类水平的能力。构建一个生产级别的深度学习模型是一项非常复杂的任务&a…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...