Linux:缓冲区的概念理解

news2024/10/2 22:12:51

文章目录

  • 缓冲区
    • 什么是缓冲区?
    • 缓冲区的意义是什么?
    • 缓冲区的刷新方式
  • 理解缓冲区
  • 用户缓冲区和内核缓冲区
  • 缓冲区在哪里?

本篇主要总结的是关于缓冲区的概念理解,以及再次基础上对文件的常用接口进行一定程度的封装

缓冲区

什么是缓冲区?

如何理解缓冲区?简单来说,缓冲区就是一段内存,用来存放一些信息,这就是对于缓冲区最初步的理解。那如何证明缓冲区的存在?用下面的代码来验证缓冲区

#include <stdio.h>
#include <unistd.h>

void buffertest()
{
    printf("hello linux");
    sleep(3);
}

int main()
{
    buffertest();
    return 0;
}

在这里插入图片描述
现象

运行结果如上所示,会先休眠三秒再输出结果,按程序的顺序结构来说,sleep一定是在printf之后执行的,也就意味着当执行到sleep的时候运行结果已经被写到了某个地方,只是还没有刷新到显示器上,因此用户看不见显示的内容,而当sleep执行完毕后,此时会把内容刷新到显示器上,这样就能看到运行的结果了

解释

而在执行了printf函数后其实就已经把内容输出了,输出的地方其实就是缓冲区中,只是还没有将信息存储到显示器这个文件内,因此没有输出结果,而当进程结束后,就会把缓冲区中的信息都刷新到显示器中,此时就实现了把信息打印到显示器上,所以才会看到,程序运行后没有输出结果,而是在执行完sleep后才会输出到显示器上

缓冲区的意义是什么?

如何理解缓冲区?有了这个缓冲区能干什么呢?答案是提高效率,对于这个答案其实并不陌生,在前面的学习中也存在有关于缓冲区的概念,只是对于缓冲区的认知程度比较低

举个例子来说,现在用户在上层使用C语言打印了很多信息,但是没有发出要刷新的需求,那么此时这些信息就都会存储在缓冲区中,而当缓冲区满了或者触发其他的刷新策略的时候,就会统一把缓冲区中的信息转移到内存中,再由内存进行其他后续的操作,在本文的后面会对这一整体的操作进行分析,此处只进行初步的描述

从外部把信息存储到内存中是需要成本的,而缓冲区的存在就是把这些信息积攒到一定程度再进行发送,既然设计出缓冲区的存在,那么就意味着把信息从缓冲区发送到内存中比直接把信息发送到内存中需要付出的成本低,这样可以提高运输的效率

缓冲区的刷新方式

缓冲区可以暂存数据,就意味着一定会有对应的刷新方式

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

一般而言是可以使用上面的刷新策略的,但是在实际的进程运行过程中可能会出现其他的意外情况,例如:

  1. 强制刷新
  2. 进程退出了,一般会刷新缓冲区

一般而言,对于显示器文件会采用的是行刷新策略,而对于磁盘上的文件会采用全缓冲的策略,对于这两种不同的刷新策略下一个模块就进行分析

理解缓冲区

下面来看这样的测试代码样例

void buffertest2()
{
    fprintf(stdout, "C:hello fprintf\n");
    printf("C:hello printf\n");
    fputs("C:hello fputs\n", stdout);
    const char* str = "system call: hello write\n";
    write(1, str, strlen(str));

    fork();
}

运行结果:

在这里插入图片描述
将运行结果输出到另外一个文件中

在这里插入图片描述
此时会发现有异常现象出现了,对于C语言的接口会打印输出两套,而对于系统调用的接口只会输出一套,那么这是为什么呢?为什么要在代码中进行fork的操作呢?fork的操作会带来怎样的影响?这两种现象出现的原因是什么呢?

对于上述现象的理解和解释

  1. 首先,对于上面的异常现象,要从出现异常的操作出发,为什么会出现异常?原因是一个是将内容直接执行,运行到显示器上,一个是把执行的结果输出到一个文件中,那么这两个操作会带来区别吗?答案是一定会的,原因就是前面提到的刷新方式的变换,对于显示器来说是行刷新策略,对于磁盘来说是全刷新策略,那么这就会带来不一样的结果,具体的原因后续分析
  2. 全缓冲意味着缓冲区会变大,实际写入的简单数据不会把缓冲区写满,因此在执行fork操作的时候,数据依旧在缓冲区中,没有被刷新到文件中
  3. 在上述的代码中所使用到的缓冲区,全部都是C语言的缓冲区,这个缓冲区是C语言本身给我们提供的,因此和操作系统内部提供的缓冲区是两种缓冲区,没有关系
  4. 那么问题来了,这和fork有什么关系呢?fork会带来什么结果呢?
  5. 那么现在就要思考的是,fork会带来什么结果,根据前面的思想不难想到,fork带来的第一个直观的效果就是创建一个子进程,这是不需要质疑的事,而对于这个进程来说,fork结束后带来的另外一个结果就是结束进程,而结束进程带来的结果就是会刷新缓冲区,既然刷新缓冲区了,那么就会把这个进程所对应的缓冲区内容清空,那么下一个问题就是关于写时拷贝的问题,缓冲区清空算不算进程的数据发生改变了呢?如果算发生改变就会发生写时拷贝,如果不算改变就不会,那么下一个问题就是进程的数据在清空缓冲区的时候算不算发生了修改
  6. 要解决上面的这个问题,本质上是思考C语言的缓冲区中的数据算不算进程运行时候的数据,因为写时拷贝的触发原理就是进程运行时候,父进程和子进程中只要有一个进程中的数据被修改,就会给另外一个进程发生写时拷贝,而这里的缓冲区的数据一定是属于进程运行时的数据的,而与此同时需要注意的是,当把数据已经交给操作系统之后,此时数据就是操作系统的,而不是进程本身的数据了,对于这样的数据即使发生修改也并不隶属于写时拷贝的范畴
  7. 那么分析到这里,其实对于上面的这个现象已经理解的很到位了,现在还有最后一个问题,为什么这个进程中对于使用系统调用的数据没有发生写时拷贝,难道这个不算是C语言缓冲区的数据,以至于这个数据不算进程的数据就不会发生写时拷贝吗?答案是肯定的,这是因为缓冲区也有很多类,而除了系统调用外的其他写入的方式都是使用的是C语言自身所提供的一个缓冲区,因此在这样的基础下进行的数据是属于进程的数据的,而使用系统调用的接口使用的数据其实并不属于,它没有使用C语言缓冲区

总结

经过上面的这几条分析,其实已经把缓冲区的概念总结的算是比较到位了,刷新其实就是把C缓冲区的数据写入操作系统

用户缓冲区和内核缓冲区

什么是用户缓冲区,什么是内核缓冲区?

用户缓冲区

用户缓冲区其实就是平时日常的使用中提供的语言级别的缓冲区,在用户层面把信息进行写入,这样的级别就是用户缓冲区所做的事,作为用户上层,进行了一系列的各种写入,这些操作都是在给用户缓冲区中写入信息,而从用户缓冲区再向着操作系统写入信息这个过程,就是刷新,经过刷新就可以把信息写入操作系统,而在操作系统内部,又会有一套完整的文件系统,关于文件系统在上一篇文章中已经完整的描述过内部的过程,这里就不再详细叙述了

内核缓冲区

既然将内容从C语言写到操作系统中需要缓冲区,那么把读取的信息刷新到磁盘中是不是也是需要缓冲区的介入呢?答案是肯定的,这是一定会有的,而这其实也是刷新,把内核缓冲区的数据写到磁盘中,也是一种刷新,只不过刷新策略和前面的C缓冲区不太一样而已,这里就对内核缓冲区不再进行过多的介绍了,它本质和硬件设备相关更多一些

缓冲区在哪里?

那这个缓冲区在哪里呢?其实也是可以找到的,调用指令进行搜索:

whereis stdio.h

打开文件,寻找FILE有关的内容

在这里插入图片描述
那么下一步就是寻找这个结构体究竟在哪里

在这里插入图片描述
在这个libio.h文件中,寻找到了这个内容,而在进行输入和输出的时候,就会有一个FILE,而FILE本质上就是一个结构体,这个结构体叫FILE里面就包含了fd,这个FILE结构体就会提供一段缓冲区

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

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

相关文章

基于ssm家庭理财系统源码和论文

基于ssm家庭理财系统源码和论文743 idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 环境&#xff1a; jdk8 tomcat8.5 开发技术 ssm 摘要 随着Internet的发展&#xff0c;人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化&#xff…

Linux_CentOS_7.9配置oracle sqlplus、rman实现上下按键切换历史命令等便捷效率功能之简易记录

配置oracle sqlplus以及rman可以上下按键切换历史命令等便捷效率功能 设置前提是已经yum安装了rlwrap软件具体软件下载及配置参考文章http://t.csdnimg.cn/iXuVK su - oracleVim .bash_profile ## 文件中增加如下的别名设置 ---------------- alias sqlplusrlwrap sqlplus…

Android音量调节参考一

基于android 9平台分析。 在Android系统中&#xff0c;默认的设备(phone等)音量都是分开控制的&#xff0c;这些包括媒体、铃声、闹铃、蓝牙、通话通过音频流来区别不同的音量类型。每种流类型都定义最大音量、最小音量及默认音量&#xff0c;Android 9定了了11中音频流类型&am…

【MATLAB】MVMD信号分解+FFT+HHT组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 MVMD信号分解FFTHHT组合算法是一种强大的分析方法&#xff0c;结合了变分模态分解(MVMD)、快速傅里叶变换(FFT)和希尔伯特-黄变换(HHT)。 首先&#xff0c;使用MVMD将原始信号分解成多个…

几分钟在Ubuntu搭建本地Emlog博客网站并发布至公网无需购买域名服务器

文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总结 前言 博客作为使…

Python-封装配置文件

Code [url] baidu http://www.baidu.com[value] send_value 百度[server] ip 220.181.111.188封装的格式可以套用 # 封装,类似函数调用 import configparserclass ReadConfigIni():def __init__(self,filename):self.cf configparser.ConfigParser()self.cf.read(filenam…

分布式搜索引擎03

1.数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如: 什么品牌的手机最受欢迎? 这些手机的平均价格、最高价格、最低价格? 这些手机每月的销售情况如何? 实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近…

[Linux] nginx配置的主配置文件

一、六个模块的作用 全局块&#xff1a;全局配置&#xff0c;对全局生效&#xff1b; events块&#xff1a;配置影响 Nginx 服务器与用户的网络连接&#xff1b; http块&#xff1a;配置代理&#xff0c;缓存&#xff0c;日志定义等绝大多数功能和第三方模块的配置&#xff1b;…

STM32 cubeMX 呼吸灯实验

文章代码使用 HAL 库。 文章目录 一、1.PWM原理二、LED 原理图三、使用cubemx 配置 led四、PWM 相关函数五、PWM占空比占空比计算六、PWM 呼吸灯重要代码总结 呼吸灯 一、1.PWM原理 PWM全称为脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;&#xff0c;是一种常…

【Linux】进程通信之命名管道mkfifo

1.认识命名管道 匿名管道应用的一个限制就是只能在具有共同祖先&#xff08;具有亲缘关系&#xff09;的进程间通信。如果我们想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件来做这项工作&#xff0c;它经常被称为命名管道。命名管道是一种特殊类型的文件 2.在命…

华清远见嵌入式学习——QT——作业1

作业要求&#xff1a; 代码&#xff1a; ①&#xff1a;头文件 #ifndef LOGIN_H #define LOGIN_H#include <QWidget> #include <QLineEdit> //行编辑器类 #include <QPushButton> //按钮类 #include <QLabel> //标签类 #include <QM…

(五) Python 代理模式

文章目录 5.1 代理模式概述5.1.1 代理介绍5.1.2 代理模式的作用 5.2 代理模式的UML类图5.3 了解不同类型的代理5.3.1虚拟代理5.3.2 远程代理5.3.3 保护代理5.3.4 智能代理 5.4 现实世界中的代理模式5.5 代理模式的优点5.6 门面模式和代理模式之间的比较 5.1 代理模式概述 5.1.…

华为鸿蒙开发——开发及引用静态共享包(HAR)、应用配置文件

文章目录 简述一、创建HAR模块二、编译HAR模块三、应用配置文件&#xff08;Stage模型&#xff09;四、应用配置文件&#xff08;FA模型&#xff09;1、配置文件的内部结构&#xff08;1&#xff09;app&#xff08;2&#xff09;deviceConfig&#xff08;3&#xff09;module …

GDPU 数据结构 天码行空13

文章目录 一、【实验目的】二、【实验内容】三、实验源代码四、实验结果五、实验总结 一、【实验目的】 (1) 理解插入排序算法的实现过程&#xff1b; &#xff08;2&#xff09;理解不同排序算法的时间复杂度及适用环境&#xff1b; &#xff08;3&#xff09;了解算法性能…

高精度时钟芯片SD2405

概要 SD2405是一款非常优秀的RTC解决方案&#xff0c;为了能让用户在Arduino上有一款方便易用的时钟模块。该模块是一款内置晶振&#xff0c;支持IIC串行接口的高精度时钟模块&#xff1b;内置一次性工业级电池&#xff0c;可保证外部掉电的情况下&#xff0c;可以继续工作5~8…

华为数通方向HCIP-DataCom H12-831题库(多选题:161-180)

第161题 以下关于IS-IS路由渗透的描述,正确的有哪些项? A、若要配置Level-2区域的路由向Level-1区域渗透,则需要在Level-1设备上配置命令import-routeisis level_-2 into level_-1 B、缺省情况下,Level-2区域无Level-1区域的路由信息,需要通过在Level-1-2设备上配置impor…

3.PyTorch——常用神经网络层

import numpy as np import pandas as pd import torch as t from PIL import Image from torchvision.transforms import ToTensor, ToPILImaget.__version__2.1.13.1 图像相关层 图像相关层主要包括卷积层&#xff08;Conv&#xff09;、池化层&#xff08;Pool&#xff09;…

翻译: 生成式人工智能的经济潜力 第2部分行业影响 The economic potential of generative AI

麦肯锡报告 翻译: 生成式人工智能的经济潜力 第一部分商业价值 The economic potential of generative AI 1. 行业影响 在我们分析的63个使用案例中&#xff0c;生成式人工智能有潜力在各行各业创造2.6万亿至4.4万亿美元的价值。其确切影响将取决于各种因素&#xff0c;比如…

SpringBoot框架+原生HTML开发,基于云端SaaS服务方式的电子病历编辑器源码

一体化电子病历编辑器源码&#xff0c;电子病历系统 一体化电子病历系统基于云端SaaS服务的方式&#xff0c;采用B/S&#xff08;Browser/Server&#xff09;架构提供&#xff0c;覆盖了医疗机构电子病历模板制作到管理使用的整个流程。除实现在线制作内容丰富、图文并茂、功能…

MySQL主从复制(一主两从)架构搭建(阿里云服务器)

建立主机master 1.建立数据库master docker run --name master --restart always -p 3308:3306 -v /root/docker/volumes/etc/master:/etc/mysql -v /root/docker/volumes/var/lib/master:/var/lib/mysql -e MYSQL_ROOT_PASSWORDriCXT8zM -d mysql:latest 2.复制master的配置文…