浅入缓冲区

365最近提款系统维护了吗 📅 2025-07-12 11:56:11 👤 admin 👁️ 172 ❤️ 734
浅入缓冲区

一概念: 对应在内存中预留的一段空间;用来缓冲输入或者输出的数据;也就是对应的输入缓冲区和输出缓冲区。

那么为什么要引入缓冲区:

每一次对文件进行的读写操作都需要执⾏⼀次系统调 ⽤,执⾏⼀次系统调⽤将涉及到CPU状态的切换,即从⽤⼾空间切换到内核空间,实现进程上下⽂的 切换,这将损耗⼀定的CPU时间,频繁的磁盘访问对程序的执⾏效率造成很⼤的影响。

如果加上了缓冲区,那么就减少磁盘的读写次数, 再加上计算机对缓冲区的操作⼤ 快于对磁盘的操作,故应⽤缓冲区可⼤ 提⾼计算机的运⾏速度。

二·缓冲类型:什么时候刷新:

1.用户强制刷新(fflush后)。

2·满足刷新条件(也就是后面三种缓冲区对应满足的条件)。

3.进程退出。

三种缓冲区类型:

①全缓冲区:当都写满了后;自动刷新到,之后调用系统的IO操作;如磁盘上普通文件的操作。

②行缓冲区:遇到换行符进行刷新;也就是对应的终端操作:显示器输入输出等就是行刷新;默认⾏缓冲区的⼤⼩为1024。

③无缓冲区:标准I/O库不对字符进⾏缓存,直接调⽤系统调⽤,如标准出错流stderr通 常是不带缓冲区的,这使得出错信息能够尽快地显⽰出来。

下面由一张图展示IO库和和系统之间进行文件操作的关系:

03207a2890014efe827d415d567536cf.png三·所谓的FILE:c语言的一个文件指针类型;其实是一个结构体;它封装了系统调用需要的fd;以及里面还封装了一个自己的缓冲区。

大致结构:

3b177541d149489f8c8e1d790cbf33dc.png后面我们会模拟实现一个简单的版本。

下面展示一段代码:

e58258128ce246f4b886d29e138e2184.png第一次执行(直接运行):

4ab0861543e0453c90a2f1748697685d.png 第二次执行:

a35383bb6bfa4c3396486de057279813.pngb46c1ec5c14d4cfabcc0bfcc7778b0a7.png四·简单实现libc库:下面我们简单的围绕缓冲区这个概念;利用我们上面所设计的知识简单实现一个模拟c库封装的用户级别的文件操作:

模拟实现相关接口函数:mfopen,mfclose,mfflush,mfwrite。

涉及知识:缓冲区,FILE结构体,语言层封装的系统层IO操作。

采用语言:c语言。

我们所谓的FILE其实就是typedef出来的:

95ab41c394094b0eadba2b566d7d8948.png这里可以理解为,每次我们利用语言层封装的fopen打开的一个文件类型不就是FILE*;也就是创造了一个这个类型结构体对象。

下面我们来实现上面所说的函数:

mystio.h:

代码语言:javascript代码运行次数:0运行复制#pragma once

#define SIZE 1024

#define FLUSH_NONE 0

#define FLUSH_LINE 1

#define FLUSH_FULL 2

struct IO_FILE

{

int fla; //文件访问方式

int fileno; //文件描述符

char outbuffer[SIZE];//缓冲区

int cap;//最大容量

int size;//当前尺寸

int flus;//刷新方式

};

typedef struct IO_FILE mFILE;

struct IO_FILE*mfopen(const char *filename, const char *mode);

int mfwrite(const void *ptr, int num, mFILE *stream);

void mfflush(mFILE *stream);

void mfclose(mFILE *stream);mystio.c:

代码语言:javascript代码运行次数:0运行复制#include"mystio.h"

#include

#include

#include

#include

#include

#include

mFILE* buyf(int fileno,int flag){

mFILE*f=(mFILE*)malloc(sizeof(mFILE));

if(f == NULL) return NULL;

f->fla=flag;

f->fileno=fileno;

f->flus=FLUSH_LINE;//默认设置成行刷新

f->cap=SIZE;

f->size=0;

memset(f->outbuffer,0,sizeof(f->outbuffer));

return f;

}

mFILE *mfopen(const char *filename,const char *mode){

umask(0);

int fd=-1;

int flag=0;

if(strcmp(mode,"r")==0){

flag = O_RDWR;

fd = open(filename, flag);

}

else if(strcmp(mode,"w")==0){

flag = O_CREAT | O_WRONLY | O_TRUNC;

fd = open(filename, flag, 0666);

}

else if(strcmp(mode, "a") == 0)

{

flag = O_CREAT | O_WRONLY | O_APPEND;

fd = open(filename, flag, 0666);

}

else{}

if(fd < 0) return NULL;

return buyf(fd, flag);

}

int mfwrite(const void *ptr, int num, mFILE *stream){

//依靠size每次判断好要写入的位置,要么直接写在后面要么遇到换行符,直接刷新出去

//这里清空操作直接用覆盖来代替(也就是把size改成0)

memcpy(stream->outbuffer+stream->size,ptr,num);

stream->size+=num;

if(stream->size>0&&stream->flus== FLUSH_LINE&&stream->outbuffer[stream->size-1]=='\n' )

{

mfflush(stream);

}

return num;

}

void mfflush(mFILE *stream){

if(stream->size>0){

write(stream->fileno,stream->outbuffer,stream->size);//写入内核缓冲区

fsync(stream->fileno);//把内核缓冲区写入磁盘

stream->size=0;

}

}

void mfclose(mFILE *stream){

if(stream->size>0){//关闭前,先看是否用户级缓冲区有数据,先写入内核缓冲区再清空

mfflush(stream);

stream->size=0;

}

close(stream->fileno);

}main.c:

代码语言:javascript代码运行次数:0运行复制#include

#include"mystio.h"

#include

#include

int main()

{

mFILE *fp = mfopen("log.txt", "a");

if(fp == NULL)

{

return 1;

}

int cnt = 5;

while(cnt)

{

printf("write %d\n", cnt);

char buffer[64];

snprintf(buffer, sizeof(buffer),"hello message, number is : %d\n", cnt);

cnt--;

mfwrite(buffer, strlen(buffer), fp);

//mfflush(fp);

sleep(1);

}

mfclose(fp);

free(stream);

}下面我们来测试一下:

测试一(每次mfwrite写入的时候以\n结尾,也就是让它实现行刷新):

ad3883c8e6084d86acd1415dd4a93a35.png测试二(每次写入的时候故意不输入\n,而是手动刷新):

04cd72cb02ae4606a81f4d438f64a5c9.png测试三(把手动刷新去掉,让它直接都写入缓冲区;最后等到mfclose关闭后自己检查缓冲区是否存在数据完成刷新):

04cd72cb02ae4606a81f4d438f64a5c9.png 今天的缓冲区小知识到此为止;希望对大家的对此认识能更加清晰,万分感谢!!!

在这篇文章的结尾,我满心感激。感谢您愿意耐心地读完我的文字,您的阅读如同阳光照亮了我创作的道路,愿我们在文字的世界里继续相伴前行,共享更多的美好与感动。

相关推荐

召唤兽装备打造过程及部分成品装备
365网站世界杯怎么进

召唤兽装备打造过程及部分成品装备

📅 07-03 👁️ 7574
厨房苍蝇太多怎么办(厨房苍蝇太多怎么办啊)
365最近提款系统维护了吗

厨房苍蝇太多怎么办(厨房苍蝇太多怎么办啊)

📅 06-29 👁️ 5097
哪个星座治得住狮子座 最旺狮子的人是谁
365最近提款系统维护了吗

哪个星座治得住狮子座 最旺狮子的人是谁

📅 06-29 👁️ 4677