【Linux】文件缓冲区

news/2024/11/29 8:49:42/

目录

  • 一、缓冲区图解
  • 二、自定义实现文件操作函数
  • 三、强制刷新内核缓冲区(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.ppmy.cn/news/1086663.html

相关文章

15 验证差分时钟输入转单端

供给FPGA的时钟有单端时钟&#xff0c;也有差分时钟&#xff0c;当输入是差分时钟时&#xff0c;需要将差分时钟转换为单端时钟输出来作为FPGA的系统工作时钟。 本次使用锁相环来实现差分到单端时钟的转换。 FPGA代码实现如下&#xff1a; TOP层 timescale 1ns / 1ps // // …

window 常用基础命令

0、起步 0-1) 获取命令的参数指引 netstat /? 0-2) 关于两个斜杠&#xff1a; window 文件路径中使用反斜杠&#xff1a;\ linux 文件路径中使用&#xff1a;/ 1、开关机类指令 shutdown /s # 关机shutdown /r # 重启shutdown /l …

目标检测YOLO算法,先从yolov1开始

学习资源 有一套配套的学习资料&#xff0c;才能让我们的学习事半功倍。 yolov1论文原址&#xff1a;You Only Look Once: Unified, Real-Time Object Detection 代码地址&#xff1a;darknet: Convolutional Neural Networks (github.com) 深度学习经典检测方法 one-stag…

【Sword系列】Vulnhub靶机HACKADEMIC: RTB1 writeup

靶机介绍 官方下载地址&#xff1a;https://www.vulnhub.com/entry/hackademic-rtb1,17/ 需要读取靶机的root目录下key.txt 运行环境&#xff1a; 虚拟机网络设置的是NAT模式 靶机&#xff1a;IP地址&#xff1a;192.168.233.131 攻击机&#xff1a;kali linux&#xff0c;IP地…

uni-app 之 图片

uni-app 之 图片 获取图片 v-bind 动态绑定 image.png <template><view><view>--- 获取图片1 ---<image src"../../static/img/tabbar_home1.png"></image></view><view>--- 获取图片2 v-bind 动态绑定---<image v-bi…

Python中重要的条件语句教程

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 一. 了解条件语句 假设一个场景&#xff1a; 同学们这个年龄去过网吧吗&#xff1f; 去网吧进门想要上网必须做的一件事是做什么&#xff1f;&#xff08;考虑重点&#xff09; 为什么要把身份证给工作人员&#xf…

嵌入式Linux开发实操(十五):nand flash接口开发(2)

通用NAND驱动程序支持几乎所有基于NAND的芯片,并将它们连接到Linux内核的内存技术设备(MTD)子系统。这个接口走的是nand的并口,可以在shell的/dev中看到设备,比如/mtd0、/mtd0ro…,mtdblock0、mtdblock1… sysfs在设备层次结构中提供了几个视角。设备必须挂在某条总线bus…

9.Redis-zset

zset zset 有序集合 -> 升序常用命令zaddzcardzcountzrangezrevrange -> reverse 逆序zrangebyscorezpopmaxzpopminbzpopmax / bzpopminzrankzrevrankzscorezremzremrangebyrankzremrangebyscorezincrby集合间操作zinter -> 交集zunion -> 并集zdiff -> 差集zin…