用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函数强制的进行刷新缓冲区。


此时就可以浅浅的解释我们开始写的代码的,因为我们的一般文件的刷新策略是缓冲区满了才刷新的,这正是因为我们向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结构体当中封装了文件描述符,其实也有缓冲区,其实就是一些指针。

         

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STL之list

目录 list定义和结构 list容器模板接受两个参数: list容器的特点 双向性 动态大小 不连续存储 实例 代码输出 需要注意的点 list常用函数 代码示例 list定义和结构 list的使用频率不高,在做题时极少遇到需要使用list的情景。 list是一种双向…

LeetCode 232.用栈实现队列(详解) (๑•̌.•๑)

题目描述: 解题思路: 创建两个栈,一个用于入数据,一个用于出数据。分别是pushST和popST; 1.如果是入数据就直接入进pushST 2.如果是出数据,先检查popST中有无数据,如果有数据,就直接出。如果没…

Xcode15 升级问题记录

这里写自定义目录标题 新版本Xcode15升级问题1:rsync error: some files could not be transferred (code 23) at ...参考 新版本Xcode15升级 下载地址:https://developer.apple.com/download/all/ 我目前使用的版本是Xcode15.2 我新创建了一个项目&…

建立四叉树[中等]

一、题目 给你一个n * n矩阵grid,矩阵由若干0和1组成。请你用四叉树表示该矩阵grid。你需要返回能表示矩阵grid的四叉树的根结点。四叉树数据结构中,每个内部节点只有四个子节点。此外,每个节点都有两个属性: 【1】val&#xff1…

使用SpringCache操作Redis缓存数据

SpringCache概念 SpringCache是一个框架,实现了基于注解的缓存功能,只需要简单的加一个注解,就能实现缓存功能。 SpringCache提供了一层抽象,底层可以切换不同的缓存实现,例如: EHCacheCaffeineRedis 使…

怎么在unity3D工程中导入Newtonsoft.Json

打开 Unity 编辑器。 转到菜单栏的 “Window”(窗口)选项,然后选择 “Package Manager”(包管理器) 在搜索框中输入 “Newtonsoft Json” 进行搜索。 注意:要选择Unity Registry 在搜索结果中&#xf…

强化学习求解TSP(五):Qlearning求解旅行商问题TSP(提供Python代码)

一、Qlearning简介 Q-learning是一种强化学习算法,用于解决基于奖励的决策问题。它是一种无模型的学习方法,通过与环境的交互来学习最优策略。Q-learning的核心思想是通过学习一个Q值函数来指导决策,该函数表示在给定状态下采取某个动作所获…

Windows下安装mariadb10.5数据库及配置详细教程

1、简介 MariaDB数据库管理系统是一款MySQL的替代数据库。MariaDB由MySQL的创始人麦克尔维德纽斯主导开发,是可扩展的,可靠的SQL服务器的合乎逻辑的选择,MariaDB 10.5 是 MariaDB 当前的稳定系列。 2、下载 下载地址:Download M…

【FPGA/verilog -入门学习17】vivado 实现串口自发自收程序

1,需求 PC使用串口助手给FPGA板发送9600 波特率的数据,FPGA板接收到数据后,回复同样的数据给PC 2,需求分析 按模块可以划分为: rx接收模块,将输入的8位并行rx 数据转换成[7:0]rx_data 信号,当…

圣诞老人遇见 GenAI:利用大语言模型、LangChain 和 Elasticsearch 破译手写的圣诞信件

在北极的中心地带,圣诞老人的精灵团队面临着巨大的后勤挑战:如何处理来自世界各地儿童的数百万封信件。 圣诞老人表情坚定,他决定是时候将人工智能纳入圣诞节行动了。 圣诞老人坐在配备了最新人工智能技术的电脑前,开始在 Jupyter…

【Linux】Ubuntu 解压 zip、z01、z02等压缩文件的方法,Linux如何解压分卷压缩的

zip分卷压缩,在windows上压缩来的,如何解压这种文件: -rw-rw-r-- 1 20401094656 Dec 10 20:06 FFHQ.z01 -rw-rw-r-- 1 20401094656 Dec 10 20:10 FFHQ.z02 -rw-rw-r-- 1 20401094656 Dec 10 23:22 FFHQ.z03 -rw-rw-r-- 1 20401094656 Dec 10…

docker微服务案例

文章目录 建立简单的springboot项目(boot3)boot2建立通过dockerfile发布微服务部署到docker容器编写Dockerfile打包成镜像运行镜像微服务 建立简单的springboot项目(boot3) 1.建立module 2. 改pom <?xml version"1.0" encoding"UTF-8"?> <…

通过反射修改MultipartFile类文件名

1、背景 项目上有这样一个需求&#xff0c;前端传文件过来&#xff0c;后端接收后按照特定格式对文件进行重命名。(修改文件名需求其实也可以在前端处理的) //接口类似于下面这个样子 PosMapping("/uploadFile") public R uploadFile(List<MultipartFile> fil…

鸿蒙HarmonyOS学习手册_入门篇

鸿蒙HarmonyOS学习手册_入门篇 文章目录 鸿蒙HarmonyOS学习手册_入门篇入门快速入门开发准备基本概念UI框架应用模型工具准备 构建第一个ArkTS应用&#xff08;Stage模型&#xff09;-快速入门-入门创建ArkTS工程ArkTS工程目录结构&#xff08;Stage模型&#xff09;构建第一个…

day14 二叉树的遍历 递归遍历 迭代遍历 统一遍历

题目1&#xff1a;递归遍历 题目链接1&#xff1a;144 二叉树的前序遍历 题意 根据二叉树的根节点root&#xff0c;返回它的前序遍历 递归法 前序遍历&#xff1a;中左右 递归三部曲 1) 确定递归函数的参数和返回值 2&#xff09;确定终止条件 3&#xff09;确定单层递…

linux搭建SRS服务器

linux搭建SRS服务器 文章目录 linux搭建SRS服务器SRS说明实验说明搭建步骤推流步骤查看web端服务器拉流步骤final SRS说明 SRS&#xff08;simple Rtmp Server&#xff09;,是一个简单高效的实时视频服务器&#xff0c;支持RTMP/WebRTC/HLS/HTTP-FLV/SRT, 是国人自己开发的一款…

计算机基础面试题 |22.精选计算机基础面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

坑记(HttpInputMessage)

一、背景知识 public interface HttpInputMessage extends HttpMessage Represents an HTTP input message, consisting of headers and a readable body.Typically implemented by an HTTP request on the server-side, or a response on the client-side.Since: 3.0 Author:…

windows安装Elasticsearch后使用ik分词器报错解决办法

最近在学习Elasticsearch&#xff0c;安装完成后下载了ik分词器压缩到plugins目录下启动es报错如下&#xff1a; java.security.AccessControlException: access denied (“java.io.FilePermission” “D:…\plugins\ik-analyzer\config\IKAnalyzer.cfg.xml” “read”)咋一看…

03 - 系统调用

---- 整理自 王利涛老师 课程 实验环境&#xff1a;宅学部落 www.zhaixue.cc 文章目录 1. 系统调用基本概念1.1 一个系统调用的例子1.2 什么是系统调用&#xff1f;软件复用的角度 2. 软中断&#xff1a;系统调用的入口2.1 权限管理2.2 系统调用号2.4 man 2 syscall2.5 实验&am…