0


【Linux】模拟实现FILE以及认识缓冲区

模拟实现FILE以及认识缓冲区

刷新缓冲逻辑图

在这里插入图片描述

自定义实现

mystdio.h
#pragmaonce #include<stdio.h>#defineNUM1024#defineBUFF_NOME0x1#defineBUFF_LINE0x2#defineBUFF_ALL0x4typedefstruct_MY_FILE{int fd;//接受描述符的值int flags;//用来记录打开方式char outputbuffer[NUM];//缓冲区保存int current;//记录缓冲区有多少字符}MY_FILE;

MY_FILE*my_fopen(constchar* path,constchar* mode);
size_t my_fwrite(constvoid* ptr,size_t size,size_t nmemb,MY_FILE* stream);intmy_fclose(MY_FILE* fp);intmy_fflush(MY_FILE* fp);
mystdio.c
#include"mystdio.h"#include<string.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdlib.h>#include<unistd.h>#include<assert.h>

MY_FILE*my_fopen(constchar* path,constchar* mode){//1.识别标志位,打开方式int flag =0;if(strcmp(mode,"r")==0) flag |= O_RDONLY;elseif(strcmp(mode,"w")==0) flag |=(O_CREAT | O_WRONLY | O_TRUNC);elseif(strcmp(mode,"a")==0) flag |=(O_CREAT | O_WRONLY | O_APPEND);elseif(strcmp(mode,"r+")==0) flag |=(O_WRONLY | O_RDONLY);elseif(strcmp(mode,"w+")==0) flag |=(O_CREAT | O_WRONLY | O_RDONLY | O_TRUNC);elseif(strcmp(mode,"a+")==0) flag |=(O_CREAT | O_WRONLY | O_RDONLY | O_APPEND);//2.尝试打开文件
  mode_t m =0666;int fd =0;if(flag | O_CREAT){
    fd =open(path,flag,m);}else{
    fd =open(path,flag);}if(fd <0)returnNULL;//3.给用户返回MY_FILE对象,需要先进行构建
  MY_FILE *mf =(MY_FILE*)malloc(sizeof(MY_FILE));if(mf ==NULL){close(fd);returnNULL;}//4.初始化MY_FILE对象
  mf->fd = fd;
  mf->flags =0;
  mf->flags |= BUFF_LINE;memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
  mf->current =0;//5.返回打开的文件return mf;}//冲刷缓冲区intmy_fflush(MY_FILE* fp){assert(fp);//将用户缓冲区的数据,通过系统调用接口,冲刷给oswrite(fp->fd,fp->outputbuffer,fp->current);
  fp ->current =0;//fsync(fp-fd);return0;}//这里返回的是字节数,不是模拟实现的输入的、个数nmemb
size_t my_fwrite(constvoid* ptr,size_t size,size_t nmemb,MY_FILE* stream){//1、缓冲区如果已经满了,就直接写入if(stream->current == NUM)my_fflush(stream);//2.根据缓冲区剩余情况,进行数据拷贝即可
  size_t user_size = size * nmemb;
  size_t my_size = NUM - stream->current;

  size_t write =0;if(my_size >= user_size){memcpy(stream->outputbuffer + stream->current,ptr,user_size);//3.更新计数器字段
    stream->current += user_size;
    write = user_size;}else{//如果缓冲区内存不够存放的话,指挥存放它的最大值memcpy(stream->outputbuffer+stream->current,ptr,my_size);
    stream->current += my_size;
    write = my_size;}//4.开始计划刷新,他们高效体现在哪里? --- TODO//不发生刷新的本质,不进行写入,就是不进行IO,不进行调用系统调用,所以my_fwrite函数调用会非常快,数据会暂时保存在缓冲区中//可以在缓冲区中挤压多份数据,统一进行刷新写入,本质:就是一次IO可以IO更多的数据,提高IO效率if(stream->flags & BUFF_ALL){if(stream->current == NUM)my_fflush(stream);}elseif(stream->flags & BUFF_LINE){if(stream->outputbuffer[stream->current-1]=='\n'){my_fflush(stream);}}else{//TODO}return write;}intmy_fclose(MY_FILE* fp){assert(fp);//1.冲刷缓冲区if(fp->current >0)my_fflush(fp);//2.关闭文件close(fp->fd);//3.释放堆空间free(fp);//4.指针置NULL --- 可以设置
  fp =NULL;return0;}
main.c
#include"mystdio.h"#include<string.h>#include<unistd.h>#include<stdio.h>#defineMYFILE"log.text"intmain(){
  MY_FILE* fp =my_fopen(MYFILE,"w");if(fp ==NULL)return1;constchar* str ="hello my my_fwrite";int cnt =10;//操作文件while(cnt){char buffer[1024];snprintf(buffer,sizeof(buffer),"%s:%d\n",str,cnt--);
    size_t size =my_fwrite(buffer,strlen(buffer),1,fp);sleep(1);printf("当前成功写入:%lu个字节\n",size);}my_fclose(fp);return0;}

如何强制刷新内核缓冲区

根据文件描述符进行强制刷新

main.c
#include"mystdio.h"#include<string.h>#include<unistd.h>#include<stdio.h>#defineMYFILE"log.text"intmain(){
  MY_FILE* fp =my_fopen(MYFILE,"w");if(fp ==NULL)return1;constchar* str ="hello my my_fwrite";int cnt =10;//操作文件while(cnt){char buffer[1024];snprintf(buffer,sizeof(buffer),"%s:%d\n",str,cnt--);if(cnt %5==0){//当cnt是五的倍数的时候就会强制刷新一次my_fwrite(buffer,strlen(buffer),1,fp);}}my_fclose(fp);return0;}

在这里插入图片描述

例子

像我们进行scanf输入的时候,其实本身我们输入的是一串字符串,将这个字符串读入对应的缓冲区buff后,然后通过分解工作,进一步传入系统,系统,系统在通过一些指令输入输出想要的结果

标签: leetcode linux 算法

本文转载自: https://blog.csdn.net/wh9109/article/details/132461723
版权归原作者 Fre丸子_ 所有, 如有侵权,请联系我们删除。

“【Linux】模拟实现FILE以及认识缓冲区”的评论:

还没有评论