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

Linux——缓冲区

我在上篇博客留下了一个问题,那个问题就是关于缓冲区的问题,我们发现
文件有缓冲区,语言有用户级缓冲区,那么缓冲区到底是什么?,或者该怎
么认识缓冲区?这篇文章或许会让你有所认识,并且在此之前我还会介绍文
件的结构体对象中的成员。

文章目录

    • 标准错误
    • 文件结构体
  • 1. 缓冲区
    • a. 引入
    • b. 缓冲区存在的意义
    • c. 产生的问题
    • d. C语言提供的缓冲区
  • 2. 尝试实现一个用户缓冲区

但是在此之前,我要补充两个知识点,一个是为什么要有标准错误,而且标准错误也是指向屏幕。还有就是介绍内核数据结构文件结构体。

标准错误

很多人都知道一个进程会默认打开三个文件标准输入,标准输出,标准错误,其中标准输入指键盘,标准输出和标准错误都是指屏幕。我们对标准输入和标准输出很熟悉,基本上每个人都使用过,但是标准错误我们可能没有用过,那么它是什么?以及为什么要有它?
它是一个文件,其实正如它的名字而言,它是记录进程错误信息的文件,那么这个文件可以是屏幕,那自然也可以是一个文本文件。像我们使用过的perror就是输出到标准错误:
在这里插入图片描述
只是我们的默认标准错误指向屏幕而已,当我们把标准错误的指向修改后:
在这里插入图片描述
在这里插入图片描述
这后面的Sucess是C语言中错误码对应的错误信息,当我们修改错误码之后:
在这里插入图片描述
在这里插入图片描述
所以标准错误可以帮助我们在进行大型的工程的时候,通过改变标准错误指向的方式将错误信息写入到特定文本文件以等待后续的处理,而正常的信息则是正常写到自己的目标文件(屏幕)里,互不干扰。

文件结构体

我们说当一个文件被打开时操作系统会创建一个结构体来描述这个文件,那现在我们就来简单认识一下该结构体中的一些成员:
在这里插入图片描述
其中f_list是用来链接系统中被打开文件的。
f_count是有多少个进程打开了文件
f_flags是文件的打开方式
f_mode是文件的权限
f_fowner是说明文件是谁打开的
f_pos表示文件的读写位置
f_mapping跟文件缓冲区有关
f_op是关于对文件操作的操作集:
在这里插入图片描述

1. 缓冲区

我们接下来的缓冲区不做特殊说明说的都是用户级别的缓冲区

a. 引入

我们现在再回顾这个问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们看到,有没有fflush,会产生出不同的结果,但是为什么第一份代码中为什么aaaaaaaa没有输入到log.txt文件中呢?这就是我们今天要说的缓冲区。这是因为write是系统调用,它写入内容到一号文件时,是直接写入到文件缓冲区中,而printf是C标准库提供的函数,它会先将内容输入到C语言提供的缓冲区中,但是我们知道,C语言缓冲区中的内容不做处理的话是直到程序运行结束的时候才会刷新,而我们在程序结束之前就将log.txt文件关闭了,那缓冲区中的aaaaaaaaa就被释放了。我们也平常会说斜杠n刷新缓冲区,但是缓冲区到底是什么呢?其实缓冲区就是平台(C语言、操作系统)提供的一块内存而已。

b. 缓冲区存在的意义

那么缓冲区存在的意义是什么呢?我们直接将内容打印到屏幕上不可以吗?当然是可以的,屏幕也是文件,当我们使用系统调用的时候会越过C语言提供的缓冲区,直接写到屏幕上。
首先,我们要对文件进行写入,本质上其实是对硬件的写入,那么假如当我们高频的对硬件进行读写的时候,那势必会将我们程序的运行速度减慢,那么这时侯,缓冲区的作用就来了,我们可以先将对文件的读写操作先写入到这个缓冲区中,然后就不用管它了,而这个缓冲区只需要以一种特定的触发方式,当触发之后再将内容写入到文件中。这么做的话就会分担我们程序的压力,从而提高我们程序的效率。写入文件的动作是必须做的,但是看的就是调取硬件的频率。
并且缓冲区中的触发机制,是缓冲区中的数据积累到一定量的时候,就会触发,从而向文件中写入,不需要多次向文件中写入,那么这也帮我们降低了写入文件的成本,从而变相的提高了我们写入文件的效率
其中的触发机制,就是我们的缓冲区的刷新机制,而缓冲区的刷新机制一般有:
即时缓冲(立即刷新)、行缓冲(行刷新)、全缓冲(缓冲区满了再刷新)。
当然也会有特殊情况:
强制刷新(fflush)、进程退出的时候自动刷新
而对于硬件而言一般来说:
显示器采用的是行刷新,磁盘采用的是全刷新

c. 产生的问题

我们会有这样的一份代码:
在这里插入图片描述
在这里插入图片描述
我们看到,当程序正常运行的时候,结果是符合我们预期的,但是当它重定向到文件的时候,文件中的内容不符合我们的预期。观察它会发现,C标准库的函数打印的内容打印了两份,而系统调用只打印了一份且顺序有所变化。
那么接下来我就带大家分析其中的原因:
程序正常运行我们就不说了,我们只说重定向的问题。
当我们重定向程序打印的内容到文件的时候,其实有一个东西偷偷的改变了,那就是缓冲区的刷新机制,由屏幕缓冲区的刷新到硬盘的刷新机制,而这也是行缓冲到全缓冲的变化。全缓冲(缓冲区是很大的)意味着不强制刷新的情况下,这一点内容是只有进程结束的时候才会刷新缓冲区内容,要注意我们在程序结束之前可是创建了一个子进程父子进程是共享代码数据的,现在就要有一个认识:用户级缓冲区也是属于进程的一份数据,那么缓冲区中的数据父子共享。所以无论父子进程哪个进程先退出,都会将自己缓冲区的内容刷新到文件中,那缓冲的内容是共享的啊,其中一个刷走之后,另一个就没有了,不合理,所以这里会发生写时拷贝,使另一个没有退出的进程仍然享有缓冲区的数据,那这时候,该进程也退出了,也要刷新缓冲区了,这时候会再次向文件中写入数据,而这就是导致重定向的时候C标准库的函数打印了两次的原因,那为什么系统调用没有打印两次呢?那是因为系统调用是直接向文件中写入的,没有经过C语言的缓冲区,也就不是我们程序的数据它已经是操作系统的数据了,不触发写时拷贝,所以就打印一次。
还有是顺序问题,这个很简单:
对于直接运行程序,由于是输出到屏幕,每一个输出的内容又都有斜杠n,所以打印的内容都是即时刷新到文件中了。
对于重定向,由于是全缓冲,系统调用不管直接刷到文件里了,而C标准库的函数还在C语言提供的缓冲区里。所以才会导致顺序发生变化。
在这里插入图片描述
而上面的向文件中写入也只是先写入到文件缓冲区中,然后由操作系统来根据自己的刷新缓冲区的触发机制来刷新缓冲区。
还有一个动词我们要明确,什么是刷新
刷新就是将缓冲区的内容写入到目的地的过程,比如将C语言提供的缓冲区中的内容写到文件缓冲区中,又或者是操作系统将文件缓冲区中的内容写入到磁盘文件中。
而C语言提供的缓冲区这种我们一般就叫做用户缓冲区
上面说的文件缓冲区是属于操作系统的,属于内核缓冲区

d. C语言提供的缓冲区

那么如果上面说的C语言给我们提供了缓冲区的话,它在哪里呢?
我们观察C标准库的关于文件操作的接口就会发现:
在这里插入图片描述
这个缓冲区其实就在FILE结构体里:
在这里插入图片描述
在这里插入图片描述

可以看到,C标准库中的FILE确实是维护着一段空间。

2. 尝试实现一个用户缓冲区

经过上面的探究,我们也试着写出一个属于自己的简单的用户级别的缓冲区,用户级别的缓冲区肯定是封装着系统调用。
头文件

#pragma oncetypedef struct myFILE
{int _fileno; //存储fdchar _buffer[1024]; //用户缓冲区int _end;//缓冲区的最后一个元素的后一个元素的下标
}myFILE;extern myFILE* my_fopen(const char* path, const char* mode);
extern int my_fputs(const char* s, myFILE* stream);
extern int my_fflush(myFILE* stream);
extern int my_fclose(myFILE* fp);

原文件

#include "mylib.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>  
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>myFILE* my_fopen(const char* path, const char* mode)
{int flags = 0;if(strcmp(mode, "r") == 0){flags |= O_RDONLY;}else if(strcmp(mode, "w") == 0){flags |= (O_CREAT|O_WRONLY|O_TRUNC);}else if(strcmp(mode, "a") == 0){flags |= (O_CREAT|O_WRONLY|O_APPEND);}else{}int fd = 0;if(flags & O_RDONLY)fd = open(path, flags);else{fd = open(path, flags, 0666);}if(fd < 0){errno = 2;return NULL;}myFILE* fp = (myFILE*)malloc(sizeof(myFILE));if(fp == NULL){errno = 3;return NULL;}fp->_end = 0;fp->_fileno = fd;return fp;
}int my_fputs(const char* s, myFILE* stream)
{memcpy(stream->_buffer + stream->_end, s, strlen(s));stream->_end += strlen(s);if(stream->_buffer[stream->_end - 1] == '\n'){my_fflush(stream);}return strlen(s);
}int my_fflush(myFILE* stream)
{if(stream->_end > 0);write(stream->_fileno, stream->_buffer, stream->_end);stream->_end = 0;return 1;
}int my_fclose(myFILE* fp)
{my_fflush(fp);close(fp->_fileno);return fp->_fileno;
}
#include <unistd.h>
#include "mylib.h"int main()
{myFILE* fp = my_fopen("log.txt", "w");const char* str = "hello world\n";int i = 0;for(i = 0; i < 20; i++){ my_fputs(str, fp);sleep(1);}my_fclose(fp);return 0;
}

在这里插入图片描述

相关文章:

Linux——缓冲区

我在上篇博客留下了一个问题&#xff0c;那个问题就是关于缓冲区的问题&#xff0c;我们发现 文件有缓冲区&#xff0c;语言有用户级缓冲区&#xff0c;那么缓冲区到底是什么&#xff1f;&#xff0c;或者该怎 么认识缓冲区&#xff1f;这篇文章或许会让你有所认识&#xff0c;…...

Mac 生成Android签名证书 .keystore文件

工具下载地址 https://www.oracle.com/java/technologies/downloads/#jdk21-mac1. 找到安装jdk的路径&#xff0c;并进入bin目录下 1.1 查找JDK命令 /usr/libexec/java_home -v结果为: java_home: option requires an argument -- v /Library/Java/JavaVirtualMachines/jdk…...

电商数仓项目----笔记六(数仓ODS层)

ODS层的设计要点如下&#xff1a; &#xff08;1&#xff09;ODS层的表结构设计依托于从业务系统同步过来的数据结构。 &#xff08;2&#xff09;ODS层要保存全部历史数据&#xff0c;故其压缩格式应选择压缩比较高的&#xff0c;此处选择gzip。 &#xff08;3&#xff09;…...

rtsp视频在使用unity三维融合播放后的修正

1 rtsp 接入 我们使用unity UE 等三维渲染引擎中使用c编写插件来接入rtsp 视频。同时做融合的时候&#xff0c;和背景的三维颜色要一致&#xff0c;这就要使用视频融合修正技术。包括亮度&#xff0c;对比度&#xff0c;饱和度的修正。在单纯颜色上的修正可以简单使用rgb->…...

【已解决】解决Springboot项目访问本地图片等静态资源无法访问的问题

今天在开发一个招聘系统的时候&#xff0c;有投递简历功能&#xff0c;有投递就会有随之而来的查看简历对吧&#xff0c;我投递过的简历&#xff0c;另存为一个文件夹&#xff0c;就是说本地磁盘(或者服务器)有一个专门存放投递过的简历的文件夹&#xff0c;用于存放PDF&#x…...

运维笔记之centos部署Go-FastDfs

安装Go-FastDfs 当前最新版本为1.4.5&#xff0c;但发布的最新版本为1.4.4 # 下载文件 wget --no-check-certificate https://github.com/sjqzhang/go-fastdfs/releases/download/v1.4.4/fileserver -O fileserver # 赋权限 chmod x fileserver # 运行 ./fileserver server服…...

C#基础——线程(线程池、线程锁、线程抢占、多线程)

线程 进程&#xff08;Process&#xff09;是由操作系统分配资源并执行的一个独立的程序实&#xff0c;属于Windows的概念&#xff0c;进程结束就表示程序关闭了。 线程&#xff08;Thread&#xff09;是程序中执行的最小单位。一个线程代表了一个独立的执行流&#xff0c;可…...

C# WPF上位机开发(QT vs WPF)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 最近经常收到朋友们的私信&#xff0c;他们对C# WPF开发很感兴趣&#xff0c;但是呢&#xff0c;正当准备学习的时候&#xff0c;又有人告诉他们应…...

2-高可用-负载均衡、反向代理

负载均衡、反向代理 upstream server即上游服务器&#xff0c;指Nginx负载均衡到的处理业务的服务器&#xff0c;也可以称之为real server,即真实处理业务的服务器。 对于负载均衡我们要关心的几个方面如下&#xff1a; 上游服务器配置&#xff1a;使用upstream server配置上…...

STM32 使用ARM仿真器设置

STM32单片机程序下载到单片机芯片中有两种方式&#xff0c;①编译生成HEX&#xff0c;使用程序烧录软件刷到单片机芯片里。②使用ARM仿真器下载程序。使用ARM仿真器的优势是&#xff0c;在工程编译没问题直接在Keil软件里就可以将程序下载到单片机里&#xff0c;并且程序可以在…...

【Java】spring

一、spring spring是一个很大的生态圈&#xff0c;里面有很多技术。 其中最基础的是spring framework&#xff0c;主要的技术 是springboot以及springcloud。 1、spring framework spring framework是spring生态圈中最基础的项目&#xff0c;是其他项目的基础。 1.1、核心…...

C语言中关于操作符的理解

本篇文章只会列出大家在生活中经常使用的操作符 算术操作符 在算数操作符中常用的有&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;% &#xff0c;我们重点讲一讲 / (除) 和 % (模) " / "运算 #include <stdio.h>int main() {int a5/2;fl…...

Flutter本地化(国际化)之App名称

文章目录 Android国际化IOS国际化 Flutter开发的App&#xff0c;如果名称想要跟随着系统的语言自动改变&#xff0c;则必须同时配置Android和IOS原生。 Android国际化 打开android\app\src\main\res\values 创建strings.xml 在values上右键&#xff0c;选择New>Values Res…...

Redis哨兵源码分析

在Redis server启动过程中&#xff0c;实现了实例化和初始化 1、哨兵实例化过程&#xff0c;采用redis sentinel指令实例化还是redis server下的参数实例化--sentinel。 // 检查服务器是否以 Sentinel 模式启动 server.sentinel_mode checkForSentinelMode(argc,argv);/* Re…...

安装Neo4j

jdk1.8对应的neo4j的版本是3.5 自行下载3.5版本的zip文件 地址 解压添加环境变量 变量名&#xff1a;NEO4J_HOME 变量值&#xff1a;D:\neo4j-community-3.5.0 &#xff08;你自己的地址&#xff09; PATH添加&#xff1a; %NEO4J_HOME%\bin (如果是挨着的注意前后英…...

华为鸿蒙开发适合哪些人学习?

随着鸿蒙系统的崛起&#xff0c;越来越多的人开始关注鸿蒙开发&#xff0c;并希望成为鸿蒙开发者。然而&#xff0c;鸿蒙开发并不适合所有人&#xff0c;那么哪些人最适合学习鸿蒙开发呢&#xff1f;本文将为您总结鸿蒙开发适合的人群。 一、具备编程基础的人 学习鸿蒙开发需要…...

深信服技术认证“SCSA-S”划重点:命令执行漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…...

Flink系列之:Savepoints

Flink系列之&#xff1a;Savepoints 一、Savepoints二、分配算子ID三、Savepoint 状态四、算子五、触发Savepoint六、Savepoint 格式七、触发 Savepoint八、使用 YARN 触发 Savepoint九、使用 Savepoint 停止作业十、从 Savepoint 恢复十一、跳过无法映射的状态恢复十二、Resto…...

使用宝塔面板部署前端项目到服务器

目录 文章目录 前言 一、第一步&#xff1a;创建文件夹 二、第二步&#xff1a;部署前端项目 三、第三步&#xff1a;打开防火墙 文章目录 前言第一步&#xff1a;创建文件夹第二步&#xff1a;部署前端项目第三步&#xff1a;打开防火墙总结 前言 在此之前&#xff0c;我…...

Enge问题解决教程

目录 解决问题的一般步骤&#xff1a; 针对"Enge问题"的具体建议&#xff1a; 以下是一些普遍适用的解决问题的方法&#xff1a; 以下是一些更深入的Enge浏览器问题和解决办法&#xff1a; 浏览器性能问题&#xff1a; 浏览器插件与网站冲突&#xff1a; 浏览…...

使用yarn安装electron时手动选择版本

访问1Password或者其他可以提供随机字符的网站&#xff0c;获取随机密码运行安装命令 操作要点&#xff0c;必须触发Couldnt find any versions for "electron" that matches "*"才算成功 将复制的随机密码粘贴到后面 例如&#xff1a;yarn add --dev elec…...

AIGC:阿里开源大模型通义千问部署与实战

1 引言 通义千问-7B&#xff08;Qwen-7B&#xff09;是阿里云研发的通义千问大模型系列的70亿参数规模的模型。Qwen-7B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样&#xff0c;覆盖广泛&#xff0c;包括大量网络文本、专业书籍…...

Java小案例-Java实现人事管理系统

前言 《人事管理系统》该项目采用技术jsp、Struts2、Mybatis、dwr、tomcat服务器、mysql数据库 开发工具eclipse/idea。 【项目使用技术】 Struts2Mybatisdwrjqueryjscss等技术 前端使用技术&#xff1a;JSP, dwr、jquery、js、css等 后端使用技术&#xff1a;Struts2Myba…...

Win系统修改Nginx配置结合内网穿透实现远程访问多个Web站点

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…...

如何使用 NFTScan NFT API 在 Base 网络上开发 Web3 应用

Base 是 Coinbase 使用 OP Stack 开发的最新以太坊第 2 层&#xff08;L2&#xff09;网络&#xff0c;用于解决以太坊等主要区块链面临的可扩展性和成本挑战。Coinbase 将其描述为“安全、低成本、对开发人员友好的以太坊 L2&#xff0c;旨在将下一个 10 亿用户带入 Web3”。B…...

【Chrome】ERR_SSL_PROTOCOL_ERROR问题

文章目录 前言一、下载二、使用步骤总结 前言 Edge升级最新版后&#xff0c;有的https访问不了&#xff0c;报如下错误 发现新版Chrome以及Chromium内核访问nginx ssl时报错&#xff0c;顺着这个思路接着查看到大佬的结论&#xff1a;服务器nginx使用的openssl版本过低&#…...

Codeforces Round 916 (Div. 3)(E:贪心 F贪心dfs G tarjan+topsort +线段树优化建图)

A&#xff1a;直接暴力统计每个字符的次数是否达标即可 #include<bits/stdc.h> using namespace std; const int N 3e510,mod998244353; #define int long long typedef long long LL; typedef pair<int, int> PII; typedef unsigned long long ULL;const long l…...

eNSP错误40,原因三:windows10自带虚拟化软件Hyper-V

问题描述 Hyper-V软件与VirtualBox不兼容&#xff0c;一旦开启Hyper-V的话eNSP的路由器就会无法开启&#xff0c;显示ERROR 40 原理 大家注意看hypervisor的两种类型&#xff1a; 左边的是开启hypervisor的Type-1&#xff0c;hypervisor在启用的时候&#xff0c;宿主机也相…...

Maven将Jar包打入本地仓库

Maven将Jar包打入本地仓库 Maven将Jar包打入本地仓库嘚吧嘚下载Maven配置Maven新建MAVEN_HOME编辑Path验证Maven配置 Jar包打入Maven仓库 Maven将Jar包打入本地仓库 嘚吧嘚 最近项目用到一个Jar包&#xff0c;不能从远程仓库拉取&#xff0c;只有一个Jar包&#xff0c;所以需…...

如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 1

本系列将分成三个部分&#xff0c;您将学习如何使用 Helm 在 Kubernetes 上集成 Prometheus 和 Grafana&#xff0c;以及如何在 Grafana 上创建一个简单的控制面板。Prometheus 和 Grafana 是 Kubernetes 最受欢迎的两种开源监控工具。学习如何使用 Helm 集成这两个工具&#x…...

自己做网站免费/网站推广步骤

精装房真的好么&#xff1f;是不是墙面可以直接贴墙纸&#xff0c;很多人都不了解嗨喽大家好&#xff0c;今天继续为大家分享家居中的那些小常识&#xff0c;今天我们要说的&#xff0c;和很多人都关注的新房有管&#xff0c;相对于毛胚房来说&#xff0c;不少人都更喜欢多花一…...

外贸建站wordpress/病毒式营销

Vue3自定义指令 除了默认设置的核心指令&#xff08;v-model和v-show&#xff09;&#xff0c;Vue也允许注册自定义指令。 下面我们注册一个全局指令v-focus&#xff0c;该指令的功能是在页面加载时&#xff0c;元素获得焦点&#xff1a; <!--* Author: RealRoad10834252…...

不用购买域名做网站/你就知道

apiary.io showdoc&#xff08;现在用的是这个&#xff0c;开源&#xff0c;有代码&#xff0c;可私网布置&#xff09; 编写 API 文档方便。 https://www.cnblogs.com/bestcode/p/6519746.html...

阿里云 网站建设/深圳优化公司样高粱seo

原 Oracle DML NOLOGGINGhttps://blog.csdn.net/tianlesoftware/article/details/5701596版权声明&#xff1a; https://blog.csdn.net/tianlesoftware/article/details/5701596 一&#xff0e; NOLOGGING 说明 在对大表插入数据的时候&#xff0c;经常会用到nologging 选项。N…...

外网如何访问群晖wordpress/搜狗广告联盟

latex常见错误&#xff01;missing $ inserted.和! File ended while scanning use of \newlbel. Latex常见的错误1 &#xff01;missing $ inserted. &#xff01;missing $ inserted.<inserted text>$ …………… 这种错误主要在使用 公式包裹的时候&#xff0c;可以忘…...

青岛知名网站建设公司/百度推广登录平台网址

导读&#xff1a;一直以来&#xff0c;众多学校教学以及公司开发环境所使用Visual Studio .NET Framework版本多不相同&#xff0c;本文作者比较了.NET Framework多个版本之间的区别&#xff0c;方便各位选择和切换.NET Framework。 版本号发布日期Visual Studio的版本Windows上…...