【Linux】文件缓冲区

目录

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

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

一、缓冲区图解

在这里插入图片描述

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

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

mystdio.h

  1 #pragma once2 3 #include<stdio.h>4 5 #define NUM 10246 #define BUFF_NONE 0x17 #define BUFF_LINE 0x28 #define BUFF_ALL  0x49 10 typedef struct MY_FILE11 {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     //将用户层缓冲区中的数据,通过系统调用接口,冲刷给OS53     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     }else79     {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.hqwc.cn/news/97187.html

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

相关文章

设计模式之建造者模式与原型模式

目录 建造者模式 简介 使用场景 优缺点 模式结构 实现 原型模式 简介 应用场景 优缺点 模式结构 实现 建造者模式 简介 将复杂对象的构建与表示进行分离&#xff0c;使得同样的构建过程可以创建不同的表示。是一个将复杂的对象分解为多个简单的对象&#xff0c;然…

医疗小程序:让服务更高效,用户体验更优化

随着移动互联网的快速发展&#xff0c;小程序已经成为了一个热门的开发方向。医疗健康类小程序也不例外&#xff0c;拥有广泛的市场需求和前景。本文将为你提供一份完整的医疗健康类小程序开发攻略&#xff0c;帮助你快速开发上线一个专业成熟的小程序商城。 一、选择合适的小程…

官方发布:Mac 版 Visual Studio IDE将于明年 8 月 31 日停止支持

近日&#xff0c;微软官方宣布&#xff1a;适用于 Mac 平台的 Visual Studio 集成开发环境&#xff08;IDE&#xff09;已经启动 "退休" 进程。Visual Studio for Mac 17.6 将继续支持 12 个月&#xff0c;持续到 2024 年 8 月 31 日。 微软表示在未来的 1 年内将重…

Altium显示/隐藏白色网络

在Altium软件中&#xff0c;相同网络的单元如果没有连接&#xff0c;会在PCB中出现白色的线&#xff0c;如下图所示。 这些白色的细线用于提示我们还有哪些网络没有布线。 如果我们不想要出现这种线&#xff0c;可以进行如下设置 View > Connections > Hide All 如…

OpenCV(十九):模板匹配

1.模板匹配&#xff1a; OpenCV提供了一个模板匹配函数&#xff0c;用于在图像中寻找给定模板的匹配位置。 2.图像模板匹配函数matchTemplate void matchTemplate( InputArray image, InputArray templ, OutputArray result, int method, InputArray mask noArray() ); image…

手写Mybatis:第14章-解析和使用ResultMap映射参数配置

文章目录 一、目标&#xff1a;ResultMap映射参数二、设计&#xff1a;ResultMap映射参数三、实现&#xff1a;ResultMap映射参数3.1 工程结构3.2 ResultMap映射参数类图3.3 添加类型处理器3.3.1 日期类型处理器3.3.2 类型处理器注册机 3.4 存放映射对象3.4.1 结果标志3.4.2 结…

深入剖析Kubernetes之声明式 API

文章目录 声明式 API编写自定义控制器 声明式 API 到底什么才是“声明式 API”呢&#xff1f; kubectl apply 命令。kubectl replace 的执行过程&#xff0c;是使用新的 YAML 文件中的 API 对象&#xff0c;替换原有的 API 对象&#xff1b;而 kubectl apply&#xff0c;则是…

Kubernetes技术--k8s核心技术Service服务

1.service概述 Service 是 Kubernetes 最核心概念,通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。 2.service存在的意义 -1:防止pod失联(服务发现) 我们先说一下什么叫pod失联。 -2:

RunnerGo:轻量级、全栈式、易用性和高效性的测试工具

随着软件测试的重要性日益凸显&#xff0c;市场上的测试工具也日益丰富。RunnerGo作为一款基于Go语言研发的开源测试平台&#xff0c;以其轻量级、全栈式、易用性和高效性的特点&#xff0c;在测试工具市场中逐渐脱颖而出。 RunnerGo是一款轻量级的测试工具&#xff0c;使用Go…

【论文阅读】自动驾驶中车道检测系统的物理后门攻击

文章目录 Abstract1.Introduction2.Background2.1.DNN-based Lane Detection2.2.Backdoor Attacks2.3.Threat Model2.4.Image Scaling 3.Methodology3.1.Physical Trigger Design3.2.Poison-Annotation Attack3.3.Clean-Annotation Attack 4.Evaluation4.1.Poison-Annotation A…

Linux环境基础开发工具

xshellssh xshell--充当客户端&#xff0c;提供远程登录服务 yum 背景知识 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放…

美团 Flink 资源调度优化实践

摘要&#xff1a;本文整理自美团数据平台计算引擎组工程师冯斐&#xff0c;在 Flink Forward Asia 2022 生产实践专场的分享。本篇内容主要分为四个部分&#xff1a; 相关背景和问题解决思路分析资源调度优化实践后续规划 点击查看原文视频 & 演讲PPT 一、相关背景和问题 在…