一.緩沖區(qū)的概念和作用
二.一個(gè)樣例
三.理解樣例
1.樣例解釋
2.什么是刷新?
四.簡(jiǎn)易模擬實(shí)現(xiàn)C標(biāo)準(zhǔn)庫
至此,我們理解了緩沖區(qū)的概念和作用,下面我們來簡(jiǎn)易模擬實(shí)現(xiàn)一下C標(biāo)準(zhǔn)庫
1.我們要實(shí)現(xiàn)的大致框架
我們要實(shí)現(xiàn)的是:
2.mylib.h的實(shí)現(xiàn)
1.文件結(jié)構(gòu)體的定義
1.首先要有一個(gè)文件結(jié)構(gòu)體:
結(jié)構(gòu)體當(dāng)中
1.要封裝文件描述符fd 設(shè)置成員變量fileno
2.用戶級(jí)緩沖區(qū)buffer 大小宏定義為SIZE 4096
3.該文件所對(duì)應(yīng)緩沖區(qū)的刷新策略 flag
刷新策略分別宏定義為
#define FLUSH_NONE 1 不刷新
#define FLUSH_LINE (1<<1) 行刷新
#define FLUSH_ALL (1<<2) 全刷新
4.緩沖區(qū)中有效數(shù)據(jù)的個(gè)數(shù) end
#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;//緩沖區(qū)中有效數(shù)據(jù)的個(gè)數(shù)(也就是最后一個(gè)有效數(shù)據(jù)的下一個(gè)位置)
int flag;//緩沖區(qū)的刷新策略
}my_file;
2.myfopen等等函數(shù)的聲明
1.myfopen:以mode的方式打開path這個(gè)文件
path:文件路徑+文件名
mode:打開文件的方式
“r”:只讀
“w”:覆蓋寫
“a”:追加寫
2.myfwrite當(dāng)中:把s字符串中前num個(gè)數(shù)據(jù)寫入stream文件中
stream:要往哪個(gè)文件當(dāng)中寫入數(shù)據(jù),stream是對(duì)應(yīng)文件的結(jié)構(gòu)體指針
s:有數(shù)據(jù)的字符串
num:要寫入的數(shù)據(jù)個(gè)數(shù)
3.myfflush:刷新文件緩沖區(qū)
4.myfclose:關(guān)閉該文件
3.完整mylib.h代碼
DFL_MODE : 打開文件的默認(rèn)權(quán)限
3.myfopen函數(shù)的實(shí)現(xiàn)
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);
}
//打開文件失敗,設(shè)置errno錯(cuò)誤碼并返回NULL
if(fd==-1)
{
errno=2;
return NULL;
}
//創(chuàng)建文件,設(shè)置fp的相應(yīng)屬性
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;
}
4.myfwrite函數(shù)的實(shí)現(xiàn)
//把s中的數(shù)據(jù)寫入stream中
int myfwrite(const char* s,int num,my_file* stream)
{
//保存舊的緩沖區(qū)的大小
int pos=stream->end;
//1.先寫入用戶級(jí)緩沖區(qū)
memcpy(stream->buffer+pos,s,num);
stream->end += num;//更新緩沖區(qū)大小
//刷新策略:按行刷新
if(stream->flag & FLUSH_LINE)
{
//2.判斷是否需要刷新緩沖區(qū)(判斷是否有'\n')
int flushit=0;
while(pos < stream->end)
{
if((stream->buffer[pos])=='\n')
{
flushit=1;
break;
}
pos++;
}
if(flushit == 1)
{
//3.刷新緩沖區(qū):[0,pos]數(shù)據(jù)
write(stream->fileno,stream->buffer,pos+1);
//4.更新緩沖區(qū) 把[pos+1,count)的數(shù)據(jù)移動(dòng)到[0,count-pos-2]當(dāng)中
//一共移動(dòng)count-pos-1個(gè)數(shù)據(jù)
//先求出要移動(dòng)的最后一個(gè)數(shù)據(jù)的下標(biāo)
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函數(shù)的實(shí)現(xiàn)
int myfflush(my_file* fp)
{
if(fp->end > 0)
{
write(fp->fileno,fp->buffer,fp->end);
fp->end=0;
}
return 0;
}
6.myfclose函數(shù)的實(shí)現(xiàn)
int myfclose(my_file* fp)
{
myfflush(fp);
return close(fp->fileno);
}
7.演示
下面我們測(cè)試一下
跟我們所預(yù)想的一樣文章來源:http://www.zghlxwxcb.cn/news/detail-838579.html
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;//緩沖區(qū)中有效數(shù)據(jù)的個(gè)數(shù)(也就是最后一個(gè)有效數(shù)據(jù)的下一個(gè)位置)
int flag;//緩沖區(qū)的刷新策略
}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);
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);
}
//打開文件失敗,設(shè)置errno錯(cuò)誤碼并返回NULL
if(fd==-1)
{
errno=2;
return NULL;
}
//創(chuàng)建文件,設(shè)置fp的相應(yīng)屬性
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中的數(shù)據(jù)寫入stream中
int myfwrite(const char* s,int num,my_file* stream)
{
//保存舊的緩沖區(qū)的大小
int pos=stream->end;
//1.先寫入用戶級(jí)緩沖區(qū)
memcpy(stream->buffer+pos,s,num);
stream->end += num;//更新緩沖區(qū)大小
//刷新策略:按行刷新
if(stream->flag & FLUSH_LINE)
{
//2.判斷是否需要刷新緩沖區(qū)(判斷是否有'\n')
int flushit=0;
while(pos < stream->end)
{
if((stream->buffer[pos])=='\n')
{
flushit=1;
break;
}
pos++;
}
if(flushit == 1)
{
//3.刷新緩沖區(qū):[0,pos]數(shù)據(jù)
write(stream->fileno,stream->buffer,pos+1);
//4.更新緩沖區(qū) 把[pos+1,count)的數(shù)據(jù)移動(dòng)到[0,count-pos-2]當(dāng)中
//一共移動(dòng)count-pos-1個(gè)數(shù)據(jù)
//先求出要移動(dòng)的最后一個(gè)數(shù)據(jù)的下標(biāo)
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);
}
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;
}
以上就是Linux文件系列: 深入理解緩沖區(qū)和C標(biāo)準(zhǔn)庫的簡(jiǎn)單模擬實(shí)現(xiàn)的全部?jī)?nèi)容,希望能對(duì)大家有所幫助!文章來源地址http://www.zghlxwxcb.cn/news/detail-838579.html
到了這里,關(guān)于Linux文件系列: 深入理解緩沖區(qū)和C標(biāo)準(zhǔn)庫的簡(jiǎn)單模擬實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!