【Linux】文件缓冲区

news2024/11/25 0:25:07

目录

  • 一、缓冲区图解
  • 二、自定义实现文件操作函数
  • 三、强制刷新内核缓冲区(fsync)

提到文件缓冲区这个概念我们好像并不陌生,但是我们对于这个概念好像又是模糊的存在脑海中,之间我们在介绍c语言文件操作已经简单的提过这个概念,今天我们不妨深入理解什么是文件缓冲区

一、缓冲区图解

在这里插入图片描述

二、自定义实现文件操作函数

通过自己实现库中的一些文件操作函数更加深入的理解文件缓冲区
自定义实现的myopen和库里面的open功能大致相同。mywrite和write大致相同。myclose和close大致相同,
通过自定义实现这些系统接口,可以更加深入的了解文件在进行读写的时候系统做了哪些事情。

mystdio.h

  1 #pragma once
  2 
  3 #include<stdio.h>
  4 
  5 #define NUM 1024
  6 #define BUFF_NONE 0x1
  7 #define BUFF_LINE 0x2
  8 #define BUFF_ALL  0x4
  9 
 10 typedef struct MY_FILE
 11 {
 12     int fd;
 13     int flags;  //flush method 刷新方式
 14     char outputbuffer[NUM]; //缓冲区
 15     int current;
 16 
 17 }MY_FILE;
 18 
 19 MY_FILE* my_fopen(const char* path,const char* mode);
 20 
 21 size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* stream);
 22 
 23 int my_fflush(MY_FILE* fp);                                                                           
 24 
 25 int my_fclose(MY_FILE*fp);

mystdio.c

  1 #include "mystdio.h"
  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 #include<malloc.h>
  8 #include<assert.h>
  9 
 10 //fopen("xxx","a");
 11 MY_FILE* my_fopen(const char* path,const char* mode)
 12 {
 13     //1.识别标志位
 14     int flag=0;
 15     if(strcmp(mode,"r")==0)flag|=O_RDONLY;
 16     else if(strcmp(mode,"w")==0)flag|=(O_CREAT | O_WRONLY | O_TRUNC);
 17     else if(strcmp(mode,"a")==0)flag|=(O_CREAT | O_WRONLY | O_APPEND);
 18     else{
 19         //other operator  "r+" ,"w+" "a+"
 20     }
 21     //2.尝试打开文件
 22     mode_t m=0666; //文件权限
 23     int fd=0;
 24     if(flag & O_CREAT)fd=open(path,flag,m);
 25     else fd=open(path,flag);
 26                                                                                                       
 27     if(fd<0)return NULL; //打开文件失败
 28 
 29     //3.给用户返回MY_FILE对象,需要构建
 30     MY_FILE* mf= (MY_FILE*)malloc(sizeof(MY_FILE));
 31     if(mf==NULL)
 32     {
 33         close(fd); //创建结构体失败,关闭文件,返回NULL                                               
 34         return NULL;
 35     }
 36 
 37     //4.初始化MY_FILE对象
 38     mf->fd = fd;
 39     mf->flags=0;
 40     mf->flags |= BUFF_LINE;
 41     memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
 42     mf->current=0;
 43     //mf->outputbuffer[0]=0; //初始化缓冲区
 44     
 45     //5.返回打开的文件
 46     return mf;
 47 }
 48 
 49 
 50 int my_fflush(MY_FILE* fp)
 51 {
 52     //将用户层缓冲区中的数据,通过系统调用接口,冲刷给OS
 53     assert(fp);
 54     write(fp->fd,fp->outputbuffer,fp->current);
 55     //...
 56     fp->current=0;
 57     return 0;
 58 }
 60 //返回实际写入的字节数
 61 size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* stream)
 62 {
 63     //1.缓冲区如果已经满了,直接写入                                                                  
 64     if(stream->current==NUM)my_fflush(stream);
 65     
 66     //2.根据缓冲区剩余情况,进行数据拷贝
 67     size_t user_size= size*nmemb; //要写入多少数据
 68     size_t my_size=NUM-stream->current; //缓冲区还剩多少空间
 69 
 70     int writen=0;
 71     if(my_size>=user_size)
 72     {
 73         //缓冲区剩余空间可以容纳要写入的数据
 74         memcpy(stream->outputbuffer+stream->current,ptr,user_size);
 75         //3.更新计数器字段
 76         stream->current += user_size;
 77         writen=user_size;
 78     }else
 79     {
 80         memcpy(stream->outputbuffer+stream->current,ptr,my_size);
 81         //3.更新计数器字段
 82         stream->current+=my_size;
 83         writen=my_size;
 84     }
 85 
 86     //3.开始计划刷新
87     //不发生刷新的本质就是不进行IO,不进行系统调用,所以my_write函数会调用非常快,数据暂时保存在缓冲区    中
 88     //可以在缓冲区积压多份数据,统一进行刷新  本质:就是一次IO可以IO更多的数据,提高IO效率
 89     if(stream->flags & BUFF_ALL)                                                                      
 90     {
 91         if(stream->current==NUM)my_fflush(stream); //全缓冲
 92     }else if(stream->flags & BUFF_LINE)
 93     {
 94         if(stream->outputbuffer[stream->current-1]=='\0')my_fflush(stream);
 95     }else{}
 96     return writen;
 97 }
 98 
 99 
100 int my_fclose(MY_FILE*fp)
101 {
102     assert(fp);
103     //1.冲刷缓冲区
104     if(fp->current>0)
105     {
106         my_fflush(fp);
107     }
108     //2.关闭文件
109     close(fp->fd);
110     //3.释放堆空间
111     free(fp);
112     //4.指针置为NULL 
113     fp=NULL;
114     return 0;
115 }

main.c

  1 #include"mystdio.h"
  2 #include<unistd.h>
  3 #include<string.h>
  4 
  5 #define MYFILE "log.txt"
  6 
  7 int main()
  8 {
  9     MY_FILE* fp=my_fopen(MYFILE,"w");
 10     if(fp==NULL)return 1;
 11 
 12 
 13     const char* msg="hello my write";
 14     int cnt=5;
 15     //操作文件
 16     while(cnt)
 17     {
 18         char buffer[1024];
 19         snprintf(buffer,sizeof(buffer),"%s:%d\n",msg,cnt--);                                          
 20         size_t size=my_fwrite(buffer,strlen(buffer),1,fp);
 21         sleep(1);
 22         printf("当前成功写入%lu个字节\n",size);
 23     }
 24     my_fclose(fp);
 25     return 0;
 26 }

运行结果
在这里插入图片描述

三、强制刷新内核缓冲区(fsync)

在这里插入图片描述

将文件缓冲区的内容强制刷新到文件中。

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

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

相关文章

NoSQL MongoDB Redis E-R图 UML类图概述

NoSQL NoSQL(Not only SQL)是对不同于传统的关系数据库的数据库管理系统的统称&#xff0c;即广义地来说可以把所有不是关系型数据库的数据库统称为NoSQL。 NoSQL 数据库专门构建用于特定的数据模型&#xff0c;并且具有灵活的架构来构建现代应用程序。NoSQL 数据库使用各种数…

CIM和websockt-实现实时消息通信:双人聊天和消息列表展示

欢迎大佬的来访&#xff0c;给大佬奉茶 一、文章背景 有一个业务需求是&#xff1a;实现一个聊天室&#xff0c;我和对方可以聊天&#xff1b;以及有一个消息列表展示我和对方&#xff08;多个人&#xff09;的聊天信息和及时接收到对方发来的消息并展示在列表上。 项目框架概…

SNP 分享:SAP S/4HANA Cloud 私有云版本及其独特优势

近几年来&#xff0c;SAP一直强调其愿景是帮助客户达成智慧型企业(Intelligent Enterprise)&#xff0c;为此其相关产品也在不断进行快速迭代&#xff0c;其核心就是S4HANA。同时SAP一直强调其要成为一家云计算公司&#xff0c;近些年也一直在推行云优先战略(Cloud First)。因此…

指针(通过指针间接访问内存)

#include <iostream> #include <algorithm> using namespace std; int main() { int a 2;//定义指针 &#xff1a; 数据类型 *指针变量名;int *p &a;cout << &a << " " << p << endl;//使用指针 &#xff1a; 可以通过…

怎么把表情包做成动态?分享一个简单的方法

表情包在我们的日常交流中已经成为了一种非常流行的表达方式&#xff0c;而将表情包做成动态则可以让它更加生动有趣。本文将介绍如何将表情包制作成动态图&#xff0c;以及一些简单的方法和制作注意事项。 制作动态表情包的方法有很多种&#xff0c;以下是其中两种简单易行的方…

SpringCloud面试题大全(Netflix+Alibaba)

SpringCloud面试题大全 ​ Spring cloud 是一个基于 Spring Boot 实现的服务治理工具包&#xff0c;用于微服务架构中管理和协调服务的。Spring Cloud 是一系列框架的有序集合。它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注…

华为云云服务器评测 | 3分钟搞懂如何在华为云服务器安装Nginx并配置静态访问页面

文章目录 一、什么是Nginx&#xff1f;二、申请华为云服务器三、使用XShell连接华为云服务器并安装Nginx四、FileZilla连接服务器五、Linux下安装Nginx❇️配置80端口并关闭Linux防火墙✳️测试 六、配置静态html至华为云服务器并访问⚠️在华为服务器新建路径⏰使用Filezilla上…

java+ssm+mysql电费管理系统

项目介绍&#xff1a; 使用javassmmysql开发的用户电费管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理、用户管理、用电管理&#xff08;用电记录、缴费提醒&#xff09;、电费…

C++多态案例-设计计算器类

1.前置知识点 多态是面向对象的三大特性之一 多态分为两类 静态多态&#xff1a;函数重载和运算符重载都属于静态多态&#xff0c;复用函数名动态多态&#xff1a;派生类和虚函数实现运行时多态 静态多态和动态多态的区别 静态多态的函数地址早绑定-----编译阶段确定函数地…

Navicat Premium 16.2.7 for Mac

Navicat Premium 16是一款功能强大的跨平台数据库管理工具&#xff0c;支持多种数据库类型&#xff0c;如MySQL、MariaDB、Oracle、SQLite、PostgreSQL等等。它提供了丰富的数据库管理功能和工具&#xff0c;可以帮助开发人员和数据库管理员快速地创建、管理和维护数据库。 Nav…

采用第11代Intel®Core处理器的多网口嵌入式边缘计算平台

Intel Core™ 11th i7/i5/i3/Celeron 处理器 及 8GB DDR4 3200Mb/s 内存4 x GbE, 3 x USB 3.2 Gen2, 1 x USB2.0, 1 x HDMI 1.4, 1 x DP 1.4a, 4 x RS232/422/485可选的第二堆栈支持多达2 x iDoor扩展&#xff0c;用于扩展无线连接、工业现场总线或更多I/O紧凑型无风扇设计零电…

1.15 自实现GetProcAddress

在正常情况下&#xff0c;要想使用GetProcAddress函数&#xff0c;需要首先调用LoadLibraryA函数获取到kernel32.dll动态链接库的内存地址&#xff0c;接着在调用GetProcAddress函数时传入模块基址以及模块中函数名即可动态获取到特定函数的内存地址&#xff0c;但在有时这个函…

做答题小程序前期需要准备哪些工作

做一个答题小程序前期需要做哪些准备工作呢&#xff1f; 第一、要有明确的答题活动规则需求&#xff0c;比如是想用个人答题形式、还是pk答题形式&#xff0c;每个模式具体的出题规则和得分规则&#xff0c;这些要计划清楚&#xff0c;让开发答题小程序的公司能够充分理解你的需…

vue3哪个数组方法在vue2上做了升级处理

在 Vue 3 中&#xff0c;v-for 指令的数组更新行为进行了升级处理。在 Vue 2 中&#xff0c;当使用 v-for 渲染数组时&#xff0c;如果对数组进行了以下操作&#xff0c;Vue 无法检测到变化&#xff1a; 直接通过索引修改数组元素&#xff0c;例如 arr[0] newValue修改数组的…

MySQL 存储引擎,你了解几个?

引言 MySQL是一种流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它支持多种不同的数据库引擎。数据库引擎是用于存储、管理和检索数据的核心组件&#xff0c;它们直接影响着数据库的性能、可靠性和功能&#xff0c;接下来本文介绍下一些常见的MySQL数据…

华为云云服务器评测 | 从零开始:云耀云服务器L实例的全面使用解析指南

文章目录 一、前言二、云耀云服务器L实例要点介绍2.1 什么是云耀云服务器L实例2.1.1 浅析云耀云服务器L实例 2.2 云耀云服务器L实例的产品定位2.3 云耀云服务器L实例优势2.4 云耀云服务器L实例支持的镜像与应用场景2.5 云耀云服务器L实例与弹性云服务器&#xff08;ECS&#xf…

MySQL基础篇:掌握数据表操作的基础知识

表(table)是一种结构化的文件&#xff0c;可以用来存储特定类型的数据&#xff0c;如&#xff1a;学生信息&#xff0c;课程信息&#xff0c;都可以放到表中。另外表都有特定的名称&#xff0c;而且不能重复。表中具有几个概念&#xff1a;列、行、主键。 列叫做字段(Column),行…

C#,《小白学程序》第十一课:双向链表(Linked-List)其二,链表的插入与删除的方法(函数)与代码

1 文本格式 /// <summary> /// 改进的车站信息类 class /// 增加了 链表 需要的两个属性 Last Next /// </summary> public class StationAdvanced { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; ///…

无涯教程-JavaScript - CUBEVALUE函数

描述 CUBEVALUE函数从多维数据集返回一个聚合值。 语法 CUBEVALUE (connection, [member_expression1], [member_expression2], …)争论 Argument描述Required/OptionalconnectionThe name of the connection to the cube. - A text stringRequiredmember_expression 多维表…

ssm+vue网络教学平台源码和论文

ssmvue网络教学平台源码和论文117 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 社会的进步&#xff0c;教育行业发展迅速&#xff0c;人们对教育越来越重视&#xff0c;在当今网络普及的情况下&#x…