【hello Linux】详解各种缓冲区

news2024/11/18 5:34:58

目录

两种缓冲区的说明

用户级缓冲区:

数据如何从用户级缓冲区——>文件内核缓冲区?

刷新策略:对于各种文件的

了解了各种知识之后,使用代码来进行更深理解的认识:



Linux🌷 

两种缓冲区的说明

先用一张图简单说明下各种缓冲区: 

缓冲区分为:用户级缓冲区和文件内核缓冲区两种;

文件是保存在磁盘中的;

如果我们使用C语言/c++等函数调用往文件里写内容时,数据会先被写入至用户级缓冲区;

如果使用wait等系统调用接口往文件中写数据的话,数据直接被写入文件内核缓冲区中;

用户级缓冲区:

printf函数输出到显示器上,是通过stdout进行的,stdout 是文件指针类型,指向一个struct file结构

体,结构体里面封装了一个 fd 和 维护了与C缓冲区相关的内容;

数据如何从用户级缓冲区——>文件内核缓冲区?

在这一步是一定要使用到 fd 的。 

1. 进程退出时; 

2. fflush()函数;

注意:

close()函数会影响刷新;

刷新策略:对于各种文件的

1. 立即刷新(不缓冲);

2. 行刷新(行缓冲\n),比如:显示器打印;

3. 缓冲区满了才刷新(全缓冲),比如:往磁盘文件中写入;


了解了各种知识之后,使用代码来进行更深理解的认识:

示例一:

#include <stdio.h>    
#include <stdlib.h>    
#include <unistd.h>    
#include <fcntl.h>                                                                                                                                                    
    
int main()    
{    
  close(1);    
  int fd = open("./log.txt", O_CREAT|O_WRONLY, 0644);    
  //在此不做打开失败的判断    
  printf("fd:%d\n",fd);    
  fprintf(stdout,"hello linux\n");    
  fprintf(stdout,"hello linux\n");    
  fprintf(stdout,"hello linux\n");    
    
  close(fd);    
  return 0;    
}   

我们发现显示器和文件中都没有内容。

原因:

我们关闭了1号文件标识符,新打开的文件被分配到1号标识符,stdout只认1号标识符;

使用C语言函数 printf 和 fprintf 进行输出,这些是函数调用,输出的内容先保存至用户级缓冲区,因为这些内容是要写入磁盘文件中的,是满了才刷新,这些数据太少达不到刷新的要求,一直保存至用户级缓冲区中,最后将fd关闭,数据刷新不到内核缓冲区中,自然也写不到磁盘文件中。

示例二:

#include <stdio.h>    
#include <stdlib.h>    
#include <unistd.h>    
#include <fcntl.h>                                                                                                                                                    
    
int main()    
{    
  close(1);    
  int fd = open("./log.txt", O_CREAT|O_WRONLY, 0644);    
  //在此不做打开失败的判断    
  printf("fd:%d\n",fd);    
  fprintf(stdout,"hello linux\n");    
  fprintf(stdout,"hello linux\n");    
  fprintf(stdout,"hello linux\n");    
    
  //close(fd);    
  return 0;    
}   

 与上个代码不同,我们不关闭fd,发现内容输出至磁盘文件中。

原因:

原本数据是存在用户级缓冲区中,return 后进程结束,会将用户级缓冲区的内容刷新至内核缓冲区中,内核缓冲区的数据自动调用一些接口将数据保存在文件中。

我们只需要知道只要能写入内核缓冲区的数据一定会写入磁盘文件中,至于怎么写入我们不必太过关心。

示例三:

#include <stdio.h>    
#include <string.h>    
#include <unistd.h>    
    
int main()    
{    
  const char* msg1 = "hello linux\n";    
  write(1,msg1,strlen(msg1));    
    
  printf("hello printf\n");    
  fprintf(stdout,"hello fprintf\n");    
    
  close(1);    
  return 0;                                                                                                                                                           
}  

上述write为系统调用接口,直接将数据写入内核缓冲区中;

printf 和 fprintf 是函数调用,将数据先写入用户级缓冲区中;

上述 printf 和 fprintf 函数最后都带了 \n,表示如果是行刷新设备则可刷新至设备中;

我们直接运行程序三个都可输出:

write直接写入内核数据缓冲区;printf 和 fprintf 输出至显示器中遇行刷新至内核缓冲区中;

所以都可以输出;

重定向的话:

三个都是往stdout中写入,按理说都可以写入文件,但出现这种现象;

本质是行刷新——>满刷新;

printf 和 fprintf 输出的内容被存到C语言级缓冲区中,满了才可以刷新,此时数据还是保存在C语言

缓冲区中,将1号文件标识符进行关闭,就算进程退出也不能将数据刷新至内核缓冲区中,因此只

输出一句;

如果不关闭close(1)发现全都可以写入文件:

 示例四:

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

执行 ./test4 出现结果的解释:

write将数据写入到内核缓冲区中,printf 和 fprintf 先写到C语言缓冲区中,因为最终输出到显示器中,遇行则刷新至内核缓冲区中,执行fork,最后进程退出,三个输出都显示到显示器上;

执行 ./test4 > log.txt 出现结果的解释:

write将数据写入到内核缓冲区中,printf 和 fprintf 先写到C语言缓冲区中,进行了重定向,本来输出到显示器的数据,现在要写入磁盘文件中,由行刷新变为满刷新,所以现在最后两个输出数据都存在C语言缓冲区中,执行fork创建了子进程,子进程拥有父进程的所有代码和数据,在子进程退出时将C语言缓冲区中的数据刷新到内核缓冲区中,然后父进程退出,将C语言缓冲区的数据刷新至内核缓冲区中,所以最后两个输出才会在log文件中显示两遍。

坚持打卡!😃

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

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

相关文章

ROS学习笔记(八):ROS2

ROS学习笔记&#xff08;八&#xff09;&#xff1a;ROS2 ROS1存在的问题ROS2ROS2的设计目标ROS2的系统架构ROS2的关键中间件——DDS ROS2的通信模型 ROS1存在的问题 ROS&#xff08;一般ROS均指ROS1&#xff09;经过多年的发展&#xff0c;已成为机器人领域的重要的工具与平台…

【社区图书馆】《uni-app跨平台开发与应用》读书随想录

目录 导言 读书感悟 《uni-app跨平台开发与应用》(从入门到实践)图书目录 作者简介 导言 最近我读了一本关于uni-app跨平台开发与应用的书籍&#xff0c;名为《uni-app跨平台开发与应用从入门到实践》。这本书让我对uni-app跨平台开发与应用有了更深入的了解&#xff0c;作…

HttpServletResponse注意事项和细节和原理示意图

目录 HttpServletResponse HttpServletResponse 介绍 HttpServletResponse 类图 向客户端返回数据方法 处理中文乱码问题-方案 处理中文乱码问题-方案 2 请求重定向 请求重定向原理示意图 应用实例 DownServlet Java类 DownServletNew.java xml配置 请求重定向注意…

Ubuntu中用VSCode交叉编译程序放到从机上运行

文章目录 前言&#xff1a;1. 前期准备&#xff1a;1.1 树莓派系统烧录与虚拟机创建1.2 VSCode拓展下载 2. 树莓派交叉编译链查询与下载2.1 交叉编译链如何判断下哪一个2.2 交叉编译链各种版本含义 3. 开始操作3.1 创建helloworld程序3.2 配置交差编译链3.3 json文件说明与配置…

变压器感量计算

1、L:感量计算LBmax*Ae*Np*R/V0.3*17.1*123*1.8/1.01.15mH 第一步:根据经验确定一个大概的感量值。 第二步:实际Sense电压波形测试&#xff0c;判断有没磁饱和&#xff0c;频率是否正确。 W功率 L感量 变压器 …

学系统集成项目管理工程师(中项)系列08a_合同管理(上)

1. 合同&#xff08;Contract&#xff09; 1.1. 契约 1.2. 广义概念 1.2.1. 以确定各种权利与义务为内容的协议&#xff0c;即只要是当事人之间达成的确定权利义务的协议均为合同&#xff0c;不管它涉及哪个法律部门及何种法律关系 1.2.2. 合同除应包括民法中的合同外&…

HTTP请求UML时序图--(POST)图和(GET)图源码分析及代码分析和MIME 介绍--常用的状态码说明

目录 WEB 开发通信协议-HTTP 什么是 HTTP 协议 介绍 http 请求 hi.html 的 UML时序图 HTTP 请求包分析 1. HTTP 请求包分析(GET)图, 说明 可以通过浏览器抓包分析 代码说明 HTML部分 JAVA部分 web.xml部分 3) 完成测试&#xff0c;并抓包分析 HTTP 请求包分析(POST…

汽车车身钣金—车身连接方式

摘要&#xff1a; 当汽车车身构件遭受严重损伤失去维修意义时,汽车维修厂商一般采用更换部件或总成的方法进行修复。 车身连接方式 当汽车车身构件遭受严重损伤失去维修意义时,汽车维修厂商一般采用更换部件或总成的方法进行修复。 车身外部覆盖件大多由相对独立的板件相互…

场效应管(MOS)基础知识

MOSFET管是常用的半导体器件&#xff0c;又称为开关管、场效应管、英文名称&#xff08;MOSFET),简称MOS管 按元件封装工艺可分为两大类:插件类、贴片类。大部分MOSFET管的外观极其类似&#xff0c;常见的封装种类有T0-252&#xff0c;T0-251&#xff0c;T0-220&#xff0c;T0—…

清华发布工具学习框架,让ChatGPT操控地图、股票查询,贾维斯已来?

文&#xff5c;小戏 首先来考大家一道初中历史题&#xff1a;人区别于动物的根本标志是什么›&#xff1f;书上的标准答案是人会制造与使用工具。那么再来一道思考题&#xff0c;如果 AI 会使用甚至会制造工具了以后&#xff0c;会发生什么呢&#xff1f;是像贾维斯一样的 AI 私…

【Java基础】day16

day16 一、switch-case 和 if-else 谁更快&#xff1f; switch-case 在 switch-case 中&#xff0c;case 的值是连续的话&#xff0c;会生成一个 TableSwitch 来进行优化&#xff0c;这样的情况下&#xff0c;只需要在表中进行判断即可。 这里使用 0-4 的连续值来进行测试 如…

UE4: Niagara系统实现雨天效果,并跟随人物移动

目录 创建雨丝Niagara系统雨丝跟随人物移动 创建雨丝Niagara系统 1.创建一个Niagara系统 选择Fountain选项&#xff0c;点一下加号&#xff0c;再点完成&#xff1a; 命名一下打开&#xff1a; 先从粒子生成的方向入手&#xff0c;在Niagara的界面中删掉“Add Velocity in…

springboot+vue小区物业管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的小区物业管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风…

C11新特性之Lambda表达式

一.lambda语法 优点&#xff1a; 1.可以定义简短的函数。 2.使用lambda表达式使代码更紧凑&#xff0c;可读性更好。 语法&#xff1a; []表示不捕获任何变量[this]表示值传递方式捕捉当前的this指针 [&]表示引用传递方式捕捉所有父作用域的变量&#xff08;包括this&…

[架构之路-170]-《软考-系统分析师》-5-数据库系统-1-数据库模式、数据模型、数据库访问的标准接口

在当今的知识经济时代&#xff0c;信息是经济发展的战略资源&#xff0c;信息技术已经成为社会生产力中重要的组成部分。人们充分认识到&#xff0c;数据库是信息化社会中信息资源管理与开发利用的基础&#xff0c;当今的计算机信息系统也都以数据库技术为基础。对于一个国家来…

Linux DNS服务

DNS 作用 DNS是 域名系统 的英文缩写&#xff0c;作为将域名与IP地址相互映射的一个分布式数据库&#xff0c;让人可以通过域名访问互联网 正向解析 将域名解析为IP反向解析 根据IP查找对应域名 域名结构 http://www.sina.com.cn./ http://主机名.子域.二级域.顶级域.根域 / 每…

【Linux学习】信号——预备知识 | 信号产生 | 核心转储

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 信号 &#x1f514;信号&#x1f3b5;预备知识&#x1f3b5;信号处理方法的注册 &#x1f514;信…

C/C++每日一练(20230421)

目录 1. 位1的个数 &#x1f31f; 2. 递归和非递归求和 ※ 3. 俄罗斯套娃信封问题 &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 位1的…

大数据技术之Kafka——Kafka入门

目录 一、概述 1.1 为什么要有Kafka ​编辑 1.2 定义 1.3 消息队列 1&#xff09;消息队列的应用场景 2&#xff09;消息队列的两种模式 1.4 基础架构 二、Producer生产者 2.1 生产者消息发送流程 2.1.1 发送原理 2.2 异步发送API 2.2.1 普通异步发送 2.2.2 带回调…

第八章_Redis复制(replica)

是什么 官网地址 一句话 就是主从复制&#xff0c;master以写为主&#xff0c;Slave以读为主 当master数据变化的时候&#xff0c;自动将新的数据异步同步到其它slave数据库 能做什么 读写分离容灾恢复数据备份水平扩容支撑高并发 怎么使用 配从(库)不配主(库) 权限细节&am…