【Linux】缓冲区

目录

一、初识缓冲区

二、用户级缓冲区

三、内核级缓冲区

四、内核级缓冲区 VS 用户级缓冲区

 五、用户级缓冲区在哪里?


一、初识缓冲区

缓冲区是什么?可以简单理解成一部分内存。例如用户缓冲区(char arr[])、C标准库提供的缓冲区、操作系统提供的缓冲区。

为什么要有缓冲区?要通过减少对磁盘的直接访问来提高文件操作的效率。例如给朋友寄快递,不是直接给朋友送过去,而是通过快递站,快递站也不是来一个包裹就送一个包裹,而是积累一部分包裹再统一发送,朋友只用到他对应的快递站取走包裹即可。提高了使用者的效率和发送的效率。

缓冲区能暂存数据,因此也要有一定的刷新方式。(一般策略)

  1. 无缓冲(立即刷新)
  2. 行缓冲(行刷新)
  3. 全缓冲(缓冲区满了,再刷新)
  4. 一般对于显示器文件,行刷新(行缓冲) ;对于磁盘上的文件,全缓冲(缓冲写满,在刷新)

特殊情况:

  1. 强制刷新 
  2. 进程退出的时候,一般要自动刷新缓冲区,即便数据没有满足刷新条件。

强制刷新缓冲区,把当前缓冲区的内容全部刷新。类似于寄快递时对工作人员说:赶快给我发出去,不然就投诉你。这时工作人员就会把驿站当前积累的包裹都发送出去。行刷新,就是把驿站快递柜的一行快递发送。全刷新,就是驿站快递柜满了,把积累的全部包裹发送出去。

看下面一段代码思考结果如何,输出重定向到文件中,结果一样吗?

#include <stdio.h>    
#include <string.h>    
#include <unistd.h>    int main()    
{    printf("C: hello printf\n");    fprintf(stdout, "C: hello fprintf\n");    fputs("C: hello fputs\n",stdout);                                                                            const char* str = "system call: hello write\n";    write(1,str,strlen(str));    fork();    return 0;    
}  

现象:直接执行程序时向显示器打印,C标准库和系统调用的函数都打印一次,但输出重定向到 log.txt 文件时,C标准库提供的函数打印两次,系统调用的函数只打印一次。

原因:

  1. 当我们直接向显示器打印的时候,显示器文件的刷新方式是行刷新!而且代码输出的所有字符串,都有'\n'。fork之前,数据全部已经被刷新,包括systemcall。
  2. 重定向到 log.txt ,本质是向磁盘文件中写入(不是显示器),系统对于数据的刷新方式已经由行缓冲,变成了全缓冲!
  3. 变成全缓冲意味着缓冲区变大,实际写入的简单数据,不足以把缓冲区写满,fork执行的时候数据依旧在缓冲区中!
  4. 我们目前所谈的"缓冲区",和操作系统是没有关系的,只能和C语言有关。(因为系统调用的结果打印正常符合预期,且C 库中的printf、fprintf、fputs实际上还是封装的wirte,如果是因为write引起的,write函数也会打印两次)

二、用户级缓冲区

我们日常用的最多的其实是C/C++标准库提供的语言级别的缓冲区,也叫用户级缓冲区。而操作系统提供的是内核级缓冲区。
在上面的例子中,我们这边的快递站就是C语言提供的用户级缓冲区,朋友就是操作系统,朋友那边的快递站就是内核级缓冲区。

上面代码原理的补充:

  • C/C++标准库提供的缓冲区,里面一定保存的是用户的数据,属于当前进程在运行时的数据。
  • 如果把用户的数据交给操作系统,那么这个数据不属于用户,属于操作系统。
  • 进程退出刷新缓冲区时,要进行刷新缓冲区,这也属于 "清空" 或 "写入" 操作。
  • C/C++缓冲区的数据属于进程的数据、fork后父子进程共享缓冲区数据,当要写入或者任一进程退出时,要刷新缓冲区,此时会发生 "写时拷贝"。
  • 可以证明write系统调用没有使用C的缓冲区,直接写入到操作系统。这个数据不属于进程。

什么叫做刷新?

一个进程有对应的文件描述符表,例如有一个打开的log.txt文件,它加载到内存中,对应一个struct file,文件描述符为3,对应一个文件缓冲区。磁盘上也有一个对应的log.txt。

用户要把"hello"字符串打印到log.txt文件,该字符串是经过fprintf等函数写入到C语言提供的缓冲区(例如名叫buffer),经过fflush或进程退出时,调用write(3,buffer)写入到文件缓冲区中。

把用户的缓冲区(例如字符数组)拷贝到C语言的缓冲区,再把C语言提供的缓冲区的内容拷贝到文件缓冲区,这个过程叫做刷新。

补充:

  • fprintf等函数不仅将打印内容拷贝到缓冲区中,还做了格式化输出操作。这个格式化输出操作是在拷贝时完成的。我们之前用的所有缓冲区都是C语言提供的用户级缓冲区。
  • 直接把数据从用户的缓冲区拷贝到文件缓冲区,成本很高,刷新操作可以提高效率
  • C语言中几乎所有的I/O接口都有缓冲区。
  • 文件缓冲区中的数据需要写入文件系统时,数据再被写入到文件系统的磁盘块中。这也是为了提高效率(减少磁盘访问)。(该操作由OS执行)

经过上面的分析,就可以更好的理解用户级缓冲区的特点:

  • 用户级缓冲区通常位于用户空间,由进程自己管理。
  • 用户级缓冲区的主要目的是提高文件操作的效率,减少系统调用的次数。
    例如,当写入文件时,数据首先被写入用户级缓冲区,然后写入内核级缓冲区,最后写入文件系统。
  • 用户级缓冲区可以被刷新,使用 'fflush' 函数可以手动刷新缓冲区,确保所有数据都被写入文件。
  • C标准库(如stdio.h)提供了文件操作的函数,如 'fopen'、'fread'、'fwrite' 等。这些函数可以在打开文件时指定缓冲区类型,如 '"w+b"'。

以下是C语言提供的几种用户级缓冲区类型:

  • 无缓冲区(无缓冲):使用 '"wb"' 或 '"rb"' 模式打开文件时,文件没有缓冲区。每次调用写入或读取函数时,数据都会立即写入或从文件中读取。
  • 行缓冲区(行缓冲):使用 '"w+b"' 或 '"r+b"' 模式打开文件时,文件有行缓冲区。每写入或读取一行数据时,数据会被缓冲,直到缓冲区满或遇到换行符。
  • 全缓冲区(全缓冲):使用 '"w+"' 或 '"r+"' 模式打开文件时,文件有全缓冲区。写入或读取的数据会被缓冲,直到缓冲区满或调用 'fflush' 函数。 

三、内核级缓冲区

上面讲到的文件缓冲区就是操作系统的内核级缓冲区
内核缓冲区通常位于内核空间,由操作系统直接管理。
标准输出(stdout)和标准错误(stderr)通常使用内核级缓冲区。
内核级缓冲区通常在进程结束时自动刷新,但在某些情况下,可以通过调用 'fflush' 函数来手动刷新这些缓冲区。
内核级缓冲区的主要目的是减少对物理设备的直接访问,提高系统性能。

用户级缓冲区和内核级缓冲区可以同时使用,以提高程序的性能。例如,当读取文件时,数据首先被读取到用户级缓冲区中,然后从用户级缓冲区读取到程序的内存中。当写入文件时,数据首先被写入程序的内存中,然后写入用户级缓冲区,最后写入内核级缓冲区,最终写入文件系统。

四、内核级缓冲区 VS 用户级缓冲区

  • 作用:内核级缓冲区主要用于减少对物理设备的直接访问,提高系统性能;而用户级缓冲区主要用于提高文件操作的效率,减少系统调用的次数。
  • 位置:内核级缓冲区位于内核空间,由操作系统管理;用户级缓冲区位于用户空间,由程序自己管理。
  • 管理:内核级缓冲区由内核直接管理,对用户不可见;用户级缓冲区由程序员控制,可以通过编程方式进行管理。
  • 性能:内核级缓冲区可以显著减少磁盘I/O操作,提高系统性能;用户级缓冲区可以减少系统调用的次数,提高程序的执行效率。

缓冲区在Linux中的主要作用:

  1. 减少磁盘访问:缓冲区允许数据在内存中暂存,而不是每次操作都直接从磁盘读取或写入。这减少了磁盘I/O操作的次数,从而提高了系统的整体性能。
  2. 优化内存使用:缓冲区可以存储大量数据,减少了对物理内存的需求。数据在内存中缓存,可以在需要时快速访问,而不是每次都从磁盘加载。
  3. 减少系统调用次数:缓冲区允许在多个操作之间缓存数据,减少了与文件系统交互的系统调用次数。这减少了内核和用户空间之间的上下文切换,提高了程序的执行效率。
  4. 提高文件操作的效率:缓冲区可以减少对文件的频繁读写,从而提高了文件操作的效率。例如,当编辑一个大型文件时,文本编辑器可以在缓冲区中修改数据,而不是每次修改都写入文件。
  5. 减少延迟:缓冲区可以减少数据传输的延迟,因为数据可以快速地在内存中传递。这使得程序可以更快速地处理数据,尤其是在处理大量数据时。
  6. 支持并行操作:缓冲区可以支持并行操作,例如,多个进程可以同时访问同一个缓冲区。这使得系统可以更有效地利用多核处理器和多进程架构。

 五、用户级缓冲区在哪里?

任何情况下,我们输出输入的时候,都要有一个FILE,FILE是一个结构体,FILE里面包含了fd,也提供了一段缓冲区!因此任何一个文件都要在C标准库里通过FILE创建一个用户级缓冲区。
例如进程打开了5个文件,就有5个FILE对象和struct file,对应5个文件缓冲区,读写时互相不影响。

可以看看C标准库中的FILE结构体:
typedef struct _IO_FILE FILE;  在   /usr/include/stdio.h

在/usr/include/libio.h
struct _IO_FILE {int _flags;     /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags//缓冲区相关/* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr;     /* Current read pointer */char* _IO_read_end;     /* End of get area. */char* _IO_read_base;     /* Start of putback+get area. */char* _IO_write_base;     /* Start of put area. */
char* _IO_write_ptr;     /* Current put pointer. */char* _IO_write_end;     /* End of put area. */char* _IO_buf_base;     /* Start of reserve area. */char* _IO_buf_end;     /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的文件描述符#if 0int _blksize;
#elseint _flags2;
#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small. */#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/* char* _save_gptr; char* _save_egptr; */_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

向显示器打印123的时候,打印的其实是1字符2字符3字符,我们用键盘输入123时,也是输入1字符2字符3字符,这3个字符被放入到stdin对应FILE结构体中的缓冲区。scanf将缓冲区的数据合并,根据用户定义的格式赋给指定的值。键盘显示器也叫字符设备。

C语言把打开的文件叫做流,输入流输出流,流也相当于C语言提供的缓冲区,一方面C语言从缓冲区的头部拿数据,一方面用户在缓冲区尾部追加数据,该操作像流水一样,所以称作‘流’。C++也是同理,也有自己的缓冲区。原理和C相同,但操作上有很大区别。

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

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

相关文章

【Transformer-BEV编码(9)】Sparse4D v2 v3源代码分析。稀疏感知方向新的baseline,相机参数泛化能力差的问题。

前言&#xff1a; 基于BEV的稠密融合算法或许并不是最优的多摄融合感知框架。同时特征级的多摄融合也并不等价于BEV。这两年&#xff0c;PETR系列(PETR, PETR-v2, StreamPETR) 也取得了卓越的性能&#xff0c;并且其输出空间是稀疏的。在PETR系列方法中&#xff0c;对于每个in…

智能边缘计算 | 2024高通边缘智能创新应用大赛赛道解读

随着物联网设备的普及和数据的井喷式增长&#xff0c;用户对数据处理的效率要求进一步提升&#xff0c;而边缘设备的计算能力日益增强&#xff0c;在边缘端完成复杂计算已经成为可能。 除降低时延与减少宽带资源占用外&#xff0c;边缘计算在离数据源更接近的地方完成数据处理…

SpringBoot环境隔离Profiles

前言 通常我们开发不可能只有一个生产环境&#xff0c;还会有其它的开发&#xff0c;测试&#xff0c;预发布环境等等。为了更好的管理每个环境的配置项&#xff0c;springboot也提供了对应的环境隔离的方法。 直接上干货 知识点 激活环境方法 1&#xff0c;在application…

Aspose.PDF功能演示:在 JavaScript 中将 TXT 转换为 PDF

您是否正在寻找一种在 JavaScript 项目中将纯文本文件从TXT无缝转换为PDF格式的方法&#xff1f;您来对地方了&#xff01;无论您是要构建 Web 应用程序、创建生产力工具&#xff0c;还是只是希望简化工作流程&#xff0c;直接从 JavaScript 代码中将 TXT 转换为 PDF 的功能都可…

Windows 安装mysql 和 Redis

mysql Windows 图形界面安装&#xff1a; 下载mysql https://dev.mysql.com/downloads/ 1.下载完成后,找到文件双击安装程序 2. 等待一段时间&#xff0c; 选择默认&#xff0c;点击next 3. 选择安装目录 下载mysql产品 安装mysql产品 产品配置向导 安装…

相关的形态

相关的形态可以分为完全线性相关、线性相关、非线性相关和不相关。 (a)中的观测点恰好落在一条直线上&#xff0c;表示了两个变量之间是一一对应的函数关系&#xff0c;可以用直线方程来准确描述这两个变量的关系&#xff0c;称为完全线性相关。 (b)中观测点散落在一条直线周…

多联机常见各部件功能及常见机组制冷原理图

一、各部件名称和主要功能 1、压缩机 压缩机根据实际系统需要&#xff0c;调整其转速达到节能目的。 2、压缩机油温加热带 在待机状态下&#xff0c;保证压缩的油温确再启动可靠性。 3、压缩机 排气 感温包 检测压缩机的排气温度&#xff0c;达到控制和保护目的。 4、高压开…

mybaties查询!!!你就说灵不灵活吧

你就说灵不灵活吧 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace"com.ruoyi.sys…

浅析扩散模型与图像生成【应用篇】(二十五)——Plug-and-Play

25. Plug-and-Play: Diffusion Features for Text-Driven Image-to-Image Translation 该文提出一种文本驱动的图像转换方法&#xff0c;输入一张图像和一个目标文本描述&#xff0c;按照文本描述对输入图像进行转换&#xff0c;得到目标图像。图像转换任务其实本质上属于图像编…

web安全学习笔记(16)

记一下第27-28课的内容。Token 验证 URL跳转漏洞的类型与三种跳转形式&#xff1b;URL跳转漏洞修复 短信轰炸漏洞绕过挖掘 一、token有关知识 什么是token&#xff1f;token是用来干嘛的&#xff1f;_token是什么意思-CSDN博客 二、URL跳转漏洞 我们在靶场中&#xff0c;…

JVS物联网模拟点位:如何配置并自动生成点位数据全教程

模拟点位 功能描述 模拟点位常用于业务的调试或数据展示&#xff0c;通过配置对应点位实现自动生成点位数据的功能。 界面操作 如下图所示&#xff0c;从模拟点位菜单进入模拟点位管理界面 模拟点位新增 点击新增按钮&#xff0c;如下图所示&#xff1a; ①&#xff1a;用户…

带插画的登录页火爆一时,不过好像有点过气了,是么?

插画在B端登录页中的作用是通过增加视觉吸引力、塑造品牌形象、提升用户体验和增加可视化指引等方式&#xff0c;为用户提供一个愉悦、易用、具有个性化的登录体验。这有助于提高用户对企业或组织的认知和好感度&#xff0c;增加用户的参与度和忠诚度。 当年这种分割很火爆呀&…