当前位置:   article > 正文

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

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

一.缓冲区的概念和作用

在这里插入图片描述

二.一个样例

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

三.理解样例

1.样例解释

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

2.什么是刷新?

在这里插入图片描述

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

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

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

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

2.mylib.h的实现

1.文件结构体的定义

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

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

刷新策略分别宏定义

#define FLUSH_NONE 1        不刷新
#define FLUSH_LINE (1<<1)   行刷新
#define FLUSH_ALL (1<<2)    全刷新
  • 1
  • 2
  • 3
4.缓冲区中有效数据的个数  end
  • 1
#define SIZE 4096

#define FLUSH_NONE 1
#define FLUSH_LINE (1<<1)
#define FLUSH_ALL (1<<2)

typedef struct my_file
{
    int fileno;
    char buffer[SIZE];
    int end;//缓冲区中有效数据的个数(也就是最后一个有效数据的下一个位置)
    int flag;//缓冲区的刷新策略
}my_file;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.myfopen等等函数的声明

在这里插入图片描述

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

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

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

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

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

3.完整mylib.h代码

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

3.myfopen函数的实现

在这里插入图片描述

my_file* myfopen(const char* path,const char* mode)
{
    int fd=0;
    int flag=0;
    if(strcmp(mode,"r")==0)
    {
        flag |= O_RDONLY;
    }
    else if(strcmp(mode,"w")==0)
    {
        flag |= (O_WRONLY | O_CREAT | O_TRUNC);
    }
    else if(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错误码并返回NULL
    if(fd==-1)
    {
        errno=2;
        return NULL;
    }
    //创建文件,设置fp的相应属性
    my_file* fp=(my_file*)malloc(sizeof(my_file));
    if(fp==NULL)
    {
        errno=3;
        return NULL;
    }
    fp->fileno=fd;
    fp->flag=FLUSH_LINE;
    fp->end=0;
    return fp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

4.myfwrite函数的实现

在这里插入图片描述

//把s中的数据写入stream中
int myfwrite(const char* 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

5.myfflush函数的实现

在这里插入图片描述

int myfflush(my_file* fp)
{
    if(fp->end > 0)
    {
        write(fp->fileno,fp->buffer,fp->end);
        fp->end=0;
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

6.myfclose函数的实现

在这里插入图片描述

int myfclose(my_file* fp)
{
    myfflush(fp);
    return close(fp->fileno);
}
  • 1
  • 2
  • 3
  • 4
  • 5

7.演示

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

8.完整代码

1.mylib.h

#pragma once
#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>

#define SIZE 4096
#define DFL_MODE 0666

#define FLUSH_NONE 1
#define FLUSH_LINE (1<<1)
#define FLUSH_ALL (1<<2)

typedef struct my_file
{
    int fileno;
    char buffer[SIZE];
    int end;//缓冲区中有效数据的个数(也就是最后一个有效数据的下一个位置)
    int flag;//缓冲区的刷新策略
}my_file;

my_file* myfopen(const char* path,const char* mode);

int myfwrite(const char* s,int num,my_file* stream);

int myfflush(my_file* fp);

int myfclose(my_file* fp);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

2.mylib.c

#include "mylib.h"

my_file* myfopen(const char* path,const char* mode)
{
    int fd=0;
    int flag=0;
    if(strcmp(mode,"r")==0)
    {
        flag |= O_RDONLY;
    }
    else if(strcmp(mode,"w")==0)
    {
        flag |= (O_WRONLY | O_CREAT | O_TRUNC);
    }
    else if(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错误码并返回NULL
    if(fd==-1)
    {
        errno=2;
        return NULL;
    }
    //创建文件,设置fp的相应属性
    my_file* fp=(my_file*)malloc(sizeof(my_file));
    if(fp==NULL)
    {
        errno=3;
        return NULL;
    }
    fp->fileno=fd;
    fp->flag=FLUSH_LINE;
    fp->end=0;
    return fp;
}


//把s中的数据写入stream中
int myfwrite(const char* 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;
}

int myfflush(my_file* fp)
{
    if(fp->end > 0)
    {
        write(fp->fileno,fp->buffer,fp->end);
        fp->end=0;
    }
    return 0;
}

int myfclose(my_file* fp)
{
    myfflush(fp);
    return close(fp->fileno);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

3.main.c

#include "mylib.h"
int main()
{
    my_file* fp=myfopen("./log.txt","a");
    if(fp==NULL)
    {
        perror("myfopen fail");
        return 1;
    }
    int cnt=10;
    
    const char* message="abc\ndef";
    while(cnt--)
    {
        mywrite(message,strlen(message),fp);
        sleep(1);
    }
    myfclose(fp);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/303545
推荐阅读
相关标签
  

闽ICP备14008679号