0


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

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

一.缓冲区的概念和作用

在这里插入图片描述

二.一个样例

在这里插入图片描述
在这里插入图片描述

三.理解样例

1.样例解释

在这里插入图片描述
在这里插入图片描述

2.什么是刷新?

在这里插入图片描述

四.简易模拟实现C标准库

至此,我们理解了缓冲区的概念和作用,下面我们来简易模拟实现一下C标准库

1.我们要实现的大致框架

我们要实现的是:
在这里插入图片描述

2.mylib.h的实现

1.文件结构体的定义

1.首先要有一个文件结构体:

结构体当中
1.要封装文件描述符fd    设置成员变量fileno
2.用户级缓冲区buffer     大小宏定义为SIZE 4096
3.该文件所对应缓冲区的刷新策略 flag

刷新策略分别宏定义为

#defineFLUSH_NONE1        不刷新#defineFLUSH_LINE(1<<1)   行刷新#defineFLUSH_ALL(1<<2)    全刷新
4.缓冲区中有效数据的个数  end
#defineSIZE4096#defineFLUSH_NONE1#defineFLUSH_LINE(1<<1)#defineFLUSH_ALL(1<<2)typedefstructmy_file{int fileno;char buffer[SIZE];int end;//缓冲区中有效数据的个数(也就是最后一个有效数据的下一个位置)int flag;//缓冲区的刷新策略}my_file;

2.myfopen等等函数的声明

在这里插入图片描述

1.myfopen:以mode的方式打开path这个文件

path:文件路径+文件名
mode:打开文件的方式
“r”:只读
“w”:覆盖写
“a”:追加写

2.myfwrite当中:把s字符串中前num个数据写入stream文件中

stream:要往哪个文件当中写入数据,stream是对应文件的结构体指针
s:有数据的字符串
num:要写入的数据个数

3.myfflush:刷新文件缓冲区
4.myfclose:关闭该文件

3.完整mylib.h代码

DFL_MODE : 打开文件的默认权限
在这里插入图片描述

3.myfopen函数的实现

在这里插入图片描述

my_file*myfopen(constchar* path,constchar* mode){int fd=0;int flag=0;if(strcmp(mode,"r")==0){
        flag |= O_RDONLY;}elseif(strcmp(mode,"w")==0){
        flag |=(O_WRONLY | O_CREAT | O_TRUNC);}elseif(strcmp(mode,"a")==0){
        flag |=(O_WRONLY | O_CREAT | O_APPEND);}if(flag & O_CREAT){
        fd=open(path,flag,DFL_MODE);}else{
        fd=open(path,flag);}//打开文件失败,设置errno错误码并返回NULLif(fd==-1){
        errno=2;returnNULL;}//创建文件,设置fp的相应属性
    my_file* fp=(my_file*)malloc(sizeof(my_file));if(fp==NULL){
        errno=3;returnNULL;}
    fp->fileno=fd;
    fp->flag=FLUSH_LINE;
    fp->end=0;return fp;}

4.myfwrite函数的实现

在这里插入图片描述

//把s中的数据写入stream中intmyfwrite(constchar* s,int num,my_file* stream){//保存旧的缓冲区的大小int pos=stream->end;//1.先写入用户级缓冲区memcpy(stream->buffer+pos,s,num);
    stream->end += num;//更新缓冲区大小//刷新策略:按行刷新if(stream->flag & FLUSH_LINE){//2.判断是否需要刷新缓冲区(判断是否有'\n')int flushit=0;while(pos < stream->end){if((stream->buffer[pos])=='\n'){
                flushit=1;break;}
            pos++;}if(flushit ==1){//3.刷新缓冲区:[0,pos]数据write(stream->fileno,stream->buffer,pos+1);//4.更新缓冲区 把[pos+1,count)的数据移动到[0,count-pos-2]当中//一共移动count-pos-1个数据//先求出要移动的最后一个数据的下标int count=stream->end;memmove(stream->buffer,stream->buffer+pos+1,count-pos-1);
            stream->buffer[count-pos-1]='\0';
            stream->end=count-pos-1;}}return num;}

5.myfflush函数的实现

在这里插入图片描述

intmyfflush(my_file* fp){if(fp->end >0){write(fp->fileno,fp->buffer,fp->end);
        fp->end=0;}return0;}

6.myfclose函数的实现

在这里插入图片描述

intmyfclose(my_file* fp){myfflush(fp);returnclose(fp->fileno);}

7.演示

下面我们测试一下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
跟我们所预想的一样

8.完整代码

1.mylib.h

#pragmaonce#include<stdio.h>#include<string.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<errno.h>#include<stdlib.h>#include<unistd.h>#defineSIZE4096#defineDFL_MODE0666#defineFLUSH_NONE1#defineFLUSH_LINE(1<<1)#defineFLUSH_ALL(1<<2)typedefstructmy_file{int fileno;char buffer[SIZE];int end;//缓冲区中有效数据的个数(也就是最后一个有效数据的下一个位置)int flag;//缓冲区的刷新策略}my_file;

my_file*myfopen(constchar* path,constchar* mode);intmyfwrite(constchar* s,int num,my_file* stream);intmyfflush(my_file* fp);intmyfclose(my_file* fp);

2.mylib.c

#include"mylib.h"

my_file*myfopen(constchar* path,constchar* mode){int fd=0;int flag=0;if(strcmp(mode,"r")==0){
        flag |= O_RDONLY;}elseif(strcmp(mode,"w")==0){
        flag |=(O_WRONLY | O_CREAT | O_TRUNC);}elseif(strcmp(mode,"a")==0){
        flag |=(O_WRONLY | O_CREAT | O_APPEND);}if(flag & O_CREAT){
        fd=open(path,flag,DFL_MODE);}else{
        fd=open(path,flag);}//打开文件失败,设置errno错误码并返回NULLif(fd==-1){
        errno=2;returnNULL;}//创建文件,设置fp的相应属性
    my_file* fp=(my_file*)malloc(sizeof(my_file));if(fp==NULL){
        errno=3;returnNULL;}
    fp->fileno=fd;
    fp->flag=FLUSH_LINE;
    fp->end=0;return fp;}//把s中的数据写入stream中intmyfwrite(constchar* s,int num,my_file* stream){//保存旧的缓冲区的大小int pos=stream->end;//1.先写入用户级缓冲区memcpy(stream->buffer+pos,s,num);
    stream->end += num;//更新缓冲区大小//刷新策略:按行刷新if(stream->flag & FLUSH_LINE){//2.判断是否需要刷新缓冲区(判断是否有'\n')int flushit=0;while(pos < stream->end){if((stream->buffer[pos])=='\n'){
                flushit=1;break;}
            pos++;}if(flushit ==1){//3.刷新缓冲区:[0,pos]数据write(stream->fileno,stream->buffer,pos+1);//4.更新缓冲区 把[pos+1,count)的数据移动到[0,count-pos-2]当中//一共移动count-pos-1个数据//先求出要移动的最后一个数据的下标int count=stream->end;memmove(stream->buffer,stream->buffer+pos+1,count-pos-1);
            stream->buffer[count-pos-1]='\0';
            stream->end=count-pos-1;}}return num;}intmyfflush(my_file* fp){if(fp->end >0){write(fp->fileno,fp->buffer,fp->end);
        fp->end=0;}return0;}intmyfclose(my_file* fp){myfflush(fp);returnclose(fp->fileno);}

3.main.c

#include"mylib.h"intmain(){
    my_file* fp=myfopen("./log.txt","a");if(fp==NULL){perror("myfopen fail");return1;}int cnt=10;constchar* message="abc\ndef";while(cnt--){mywrite(message,strlen(message),fp);sleep(1);}myfclose(fp);return0;}

以上就是Linux文件系列: 深入理解缓冲区和C标准库的简单模拟实现的全部内容,希望能对大家有所帮助!


本文转载自: https://blog.csdn.net/Wzs040810/article/details/135190528
版权归原作者 program-learner 所有, 如有侵权,请联系我们删除。

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

还没有评论