深入理解C语言对文件的包装与缓冲区 |
您所在的位置:网站首页 › c语言之文件操作 › 深入理解C语言对文件的包装与缓冲区 |
内存级文件操作的运用
1.模拟实现文件分装2. 深入理解缓冲区的概念
1.模拟实现文件分装
【目标】 以最简单的方式,理解FILE结构体的原理。 头文件:mystdio.h(定义了MY_FILE结构体,声明fopen,fwrite,fclose,fflush函数) #pragma once #include #define NUM 1024 #define BUFFER_NONE 1 #define BUFFER_LINE 2 #define BUFFER_ALL 4 typedef struct MY_FILE { int fd; int flags;//flush method char outputbuffer[NUM]; int current; }MY_FILE; MY_FILE* my_fpen(const char *path, const char *mode); size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, MY_FILE *stream); int my_fclose(MY_FILE *fp); int my_fflush(MY_FILE *fp);mystdio.c文件:相关函数的实现 #include"mystdio.h" #include #include #include #include #include #include #include //fopen("a/b/c","a") //fopen("a/b/c","r") //fopen("a/b/c","w") MY_FILE* my_fpen(const char *path, const char *mode) { //1.识别标志位,确定打开方式 int flag=0; if(strcmp(mode,"r")==0)flag|=O_RDONLY; else if(strcmp(mode,"w")==0)flag|=(O_CREAT|O_WRONLY|O_TRUNC); else if(strcmp(mode,"a")==0)flag|=(O_CREAT|O_WRONLY|O_APPEND ); else {//other open method ; } //2.尝试打开文件 mode_t m=0666; int fd=0; if(flag&O_CREAT)fd=open(path,flag,m); else fd=open(path,flag); if(fd assert(ptr&&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 writen=0; if(my_size>user_size) { memcpy(stream->outputbuffer+stream->current,ptr,user_size); //3.更新计数器字段 stream->current+=user_size; writen=user_size; } else { memcpy(stream->outputbuffer+stream->current,ptr,my_size); //3.更新计数器字段 stream->current+=my_size; writen=my_size; } //4.开始计划刷新数据,看看他们高效体现在哪里? //不发生刷新的本质,不进行写入,就是不进行IO,不进行调用系统调用,所以my_fwrite函数调用会非常快,数据会暂时保存在缓冲区中 //可以在缓冲区中挤压多分数据,统一进行刷新写入,本质:就是一次IO可以IO更多的数据,提高IO效率 if(stream->flags&BUFFER_ALL) { if(stream->current==NUM)my_fflush(stream); } else if(stream->flags&BUFFER_LINE) { if(stream->outputbuffer[stream->current-1]=='\n')my_fflush(stream); } else { //TODO } return writen/nmemb; } int my_fclose(MY_FILE *fp) { assert(fp); //1.冲刷缓冲区 if(fp->current>0)my_fflush(fp); //2.关闭文件 close(fp->fd); //3.释放栈空间 free(fp); return 0; } int my_fflush(MY_FILE* fp) { assert(fp); //将用户缓冲区中的数据,通过系统接口,冲刷给OS write(fp->fd,fp->outputbuffer,fp->current); fp->current=0; fsync(fp->fd); return 0; }main函数 #include"mystdio.h" #include #include #define MYFILE "log.txt" int main() { MY_FILE *fp=my_fpen(MYFILE,"w"); if(fp==NULL) { printf("打开文件失败!\n"); return 1; } //文件操作 const char *str="hello my fwrite"; int cnt=5; while(cnt) { char buff[1024]=""; snprintf(buff,sizeof(buff),"%s:%d\n",str,cnt--); size_t size=my_fwrite(buff,strlen(buff),1,fp); sleep(1); printf("当前成功写入%lu个字符!\n",size); } my_fclose(fp); return 0; } 2. 深入理解缓冲区的概念因为冯诺依曼体系的原因,多次的IO访问外设,速度会很慢。通过缓冲区,可以临时存储数据,再根据缓冲区刷新策略,进行一次IO将数据写入到外设中。IO次数减少,速度明显提高。 缓冲区分成有两种:用户级缓冲区+内核级缓冲区。 用户级别的缓冲区是语言提供的,按照刷新策略调用系统接口,将数据写入到内核级别的缓冲区中;内核级别的缓冲区是不可见的,也有自己的刷新策略,由OS来控制。刷新内核级别的缓冲区才是将数据存储到磁盘上面。 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |