【Linux】文件缓冲区

这篇具有很好参考价值的文章主要介绍了【Linux】文件缓冲区。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

一、缓冲区图解

【Linux】文件缓冲区,Linux,linux,网络

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

通过自己实现库中的一些文件操作函数更加深入的理解文件缓冲区
自定义实现的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 }

运行结果
【Linux】文件缓冲区,Linux,linux,网络

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

【Linux】文件缓冲区,Linux,linux,网络

将文件缓冲区的内容强制刷新到文件中。文章来源地址https://www.toymoban.com/news/detail-694622.html

到了这里,关于【Linux】文件缓冲区的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux文件系列: 深入理解缓冲区和C标准库的简单模拟实现

    至此,我们理解了缓冲区的概念和作用,下面我们来简易模拟实现一下C标准库 我们要实现的是: 1.文件结构体的定义 1.首先要有一个文件结构体: 刷新策略分别宏定义为 2.myfopen等等函数的声明 path:文件路径+文件名 mode:打开文件的方式 “r”:只读 “w”:覆盖写 “a”:追加写 strea

    2024年03月11日
    浏览(66)
  • [Linux]理解文件系统!动静态库详细制作使用!(缓冲区、inode、软硬链接、动静态库)

            hello,大家好,这里是bang___bang_,今天来谈谈的文件系统知识,包含有缓冲区、inode、软硬链接、动静态库。本篇旨在分享记录知识,如有需要,希望能有所帮助。 目录 1️⃣缓冲区 🍙缓冲区的意义 🍙常见缓冲区刷新策略 🍙缓冲区位置猜想 🍥现象猜测 🍥现象解

    2024年02月13日
    浏览(47)
  • 【看表情包学Linux】文件描述符 | 重定向 Redirection | dup2 函数 | 缓冲区的理解 (Cache)

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 在上一章中,我们已经把 fd 的基本原理搞清楚了。本章我们将开始探索 fd 的应用特征,探索 文件描述符的分配原则。讲解重定向,上一章是如何使用 fflush 把内容变出来的,介绍 dup2 函数,

    2023年04月25日
    浏览(53)
  • 【Linux】理解缓冲区

    我们发现 printf 和 fwrite (库函数)都输出了2次,而 write 只输出了一次(系统调用)。为什么呢?肯定和fork有关! C接口的函数被打印了两次系统接口前后只是打印了一次:和fork函数有关,fork会创建子进程。在创建子进程的时候,数据会被处理成两份,父子进程发生写时拷

    2024年01月23日
    浏览(52)
  • 【Linux】深入理解缓冲区

    目录 什么是缓冲区 为什么要有缓冲区 缓冲区刷新策略 缓冲区在哪里  手动设计一个用户层缓冲区 缓冲区本质上一块内存区域,用来保存临时数据。 缓冲区在各种计算任务中都广泛应用,包括输入/输出操作、网络通信、图像处理、音频处理等。 这块内存区域是由 谁提供的

    2024年02月15日
    浏览(62)
  • 【linux】重定向+缓冲区

    自我名言 : 只有努力,才能追逐梦想,只有努力,才不会欺骗自己。 喜欢的点赞,收藏,关注一下把! close(1),为什么没有打印新建文件fd呢? printf(“%dn”,fd); printf会把内容打印到stdout文件中。 但是close(1)关闭标准输出stdout—显示器,int fd=open();新打开的文件fd是1。 st

    2024年02月08日
    浏览(54)
  • Linux之缓冲区的理解

    目录 一、问题引入 二、缓冲区 1、什么是缓冲区 2、刷新策略 3、缓冲区由谁提供 4、重看问题 三、缓冲区的简单实现 我们先来看看下面的代码:我们使用了C语言接口和系统调用接口来进行文件操作。在代码的最后,我们还使用fork函数创建了一个子进程。  代码运行结果如

    2024年02月03日
    浏览(48)
  • 浅谈linux缓冲区的认识!

    今天来为大家分享一波关于缓冲区的知识!那么既然我们要谈缓冲区,那么就得从是什么?为什么?有什么作用这几个方面来谈论一下缓冲区!然后再通过一些代码来更加深刻的理解缓冲区的知识! 从最简单的理解方面来,我们可以将缓冲区理解成一块内存!那么这块内存是

    2024年02月05日
    浏览(54)
  • 【Linux】缓冲区+磁盘+动静态库

    缓冲区的本质就是一段用作缓存的 内存 。 节省进程进行数据IO的时间。进程使用fwrite等函数把数据拷贝到缓冲区或者外设中。 3.1、 立即刷新(无缓冲)——ffush() 情况很少,比如调用printf后,手动调用fflush刷新缓冲区。 3.2、 行刷新(行缓冲)——显示器 显示器需要满足人

    2024年02月05日
    浏览(39)
  • 【Linux】基础IO----理解缓冲区

    作者:დ旧言~ 座右铭:松树千年终是朽,槿花一日自为荣。 目标:理解缓冲区 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! 专栏选自:Linux初阶 望小伙伴们点赞👍收藏✨加关注哟💕💕 缓冲区大家其实不陌生,像我们使用的 VS2019 编译器这里就有缓冲区,那它

    2024年04月13日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包