网站怎样自动文字排版,网站代理服务器有问题,网站视频主持人,做58网站怎么赚钱linux基础io重定向-CSDN博客 文章目录 目录
文章目录
什么是缓冲区
为什么要有缓冲区
二、编写自己的fopen、fwrite、fclose
1.引入函数
2、引入FILE
3.模拟封装
1、fopen
2、fwrite
3、fclose
4、fflush
总结 前言
用快递站讲述缓冲区
收件区#xff08;类比输… linux基础io重定向-CSDN博客 文章目录 目录
文章目录
什么是缓冲区
为什么要有缓冲区
二、编写自己的fopen、fwrite、fclose
1.引入函数
2、引入FILE
3.模拟封装
1、fopen
2、fwrite
3、fclose
4、fflush
总结 前言
用快递站讲述缓冲区
收件区类比输入缓冲区
快递站的收件区就如同计算机的输入缓冲区。当快递员不断送来包裹好比计算机从外部设备接收数据收件区先把这些包裹暂存起来。就像计算机通过输入设备如键盘输入字符、网络传来数据等接收到的数据不会立刻被全部处理而是先放在输入缓冲区。例如很多快递在一天内不同时段被送来收件区堆积着这些待进一步处理的包裹这类似输入缓冲区存放着源源不断接收到的数据等待后续的处理步骤。
分拣区类比处理缓冲区
这里可比作计算机的处理缓冲区。在快递站分拣区工作人员会对包裹进行查看、分类依据目的地等信息这类似计算机处理缓冲区对暂存的数据进行分析、判断处理方式。比如要确定数据该送往哪个程序或存储区域进行下一步操作就如同分拣区确定包裹该发往哪个派送点。而且有时候包裹会在分拣区排队等待进一步转运安排这也如同数据在处理缓冲区可能会因处理资源不足等原因排队等待处理以确保按正确顺序完成处理。
发件区类比输出缓冲区
快递站的发件区就像计算机的输出缓冲区。分拣好准备发往各个派送点的包裹会在发件区暂存如同计算机处理好的数据在输出缓冲区暂存等待快递车辆来运走类似等待合适时机输出到外部设备。比如一批要发往同一区域的包裹先在发件区集合就如同一组要输出到显示器显示的数据先在输出缓冲区等待统一发送以便正确显示。同时发件区工作人员要协调快递车辆到来时间等保证包裹有序发出这类似输出缓冲区要协调与外部设备的连接及数据传输时机确保数据准确输出到目标设备。
总之快递站的不同区域通过暂存、处理、再暂存并协调输出的流程很好地模拟了计算机缓冲区在接收、处理、输出数据过程中的作用。 一、缓冲区是什么
缓冲区是计算机存储体系中的一个特定区域主要起到暂存数据的作用。
在输入方面 当外部设备如键盘、鼠标、网络等向计算机输入数据时数据不会立刻被计算机核心部件如CPU处理而是先进入输入缓冲区暂存。比如你通过键盘快速打字字符数据会先堆积在输入缓冲区等待后续按合适的速度和顺序被处理避免因输入速度过快而导致数据丢失或处理混乱。
在输出方面 当计算机内部处理好的数据要输出到外部设备如显示器、打印机等时也会先暂存到输出缓冲区。例如计算机要在显示器上显示一幅图像处理好的图像数据会先放在输出缓冲区然后再按照显示器的刷新频率等要求适时且有序地将数据传输到显示器进行显示这样能保证输出的稳定性和连贯性。
在数据处理过程中 有时数据在不同部件如CPU和内存之间、不同程序之间等流转时也会在中间设置缓冲区来暂存数据起到协调数据传输速度差异、避免数据冲突等作用。
总之缓冲区就像是数据流转过程中的一个个“临时仓库”让数据的输入、输出和处理都能更顺畅、有序地进行。
什么是缓冲区
缓冲区本质上一块内存区域用来保存临时数据。缓冲区在各种计算任务中都广泛应用包括输入/输出操作、网络通信、图像处理、音频处理等。
这块内存区域是由谁提供的呢缓冲区在哪里呢可以继续向下看.
这里先告诉答案是C标准库提供的.
为什么要有缓冲区
缓冲区用于解决数据传输速度不匹配或不稳定的问题并提高数据处理的效率。
当从硬盘读取大量数据时将数据直接传输到内存中可能会导致读写速度不匹配(内存速度快而硬盘读取速度慢这是相对来说的)从而导致性能瓶颈。为了缓解这个问题可以引入一个缓冲区先将一部分数据读取到缓冲区中然后再从缓冲区逐步读取数据到内存中以平衡数据传输速度。
这里有个很合适的例子来解释
例如你和你的朋友在两个不同的大学相差大概500公里有一天你想送一些书给你的朋友此时你可以选择骑自行车亲自骑行去送这些书礼轻情意重嘛加上中途休息然后由于速度慢花了大概一周的时间才到送了之后然后又骑回自己的学校又花了一周的时间一共过了两周完整的工作才完成耗时太长。
假设此时你学聪明了既然那么慢那么直接坐高铁去送可来回一共都500多了这都比这些书的价值多了即成本太高了.
可以把以上这些书看做资源这种模式叫做写透模式.
此时你想到可以寄快递来送这些书啊价格便宜而且两三天就到了这多实惠于是你把这些书交给了顺丰 快递过了两三天你的朋友在手机上给你说说我收到这些书了然后这样就成功的把资源交到了对方的手中。这个顺丰快递在这里扮演的角色便是缓冲区.
顺丰 拿到你的快递也不是立马就送而是等待数量足够多时再一次性开始运输这相当于是一种缓冲区的刷新策略.
缓冲区刷新策略 刷新策略主要有以下3种
1.立即刷新
2.行刷新(行缓冲)遇到\n刷新
3.满刷新(全缓冲)指的是将输入或输出的数据完全存储在缓冲区中然后再进行传输或处理。
当然也会有一些特殊情况
1.用户强制刷新(fflush)
2.进程退出
遇到以上两种情况时必须马上从刷新缓冲区的数据而不要按照之前的刷新策略继续等待.
所以缓冲策略 一般情况 特殊情况.
一般而言行缓冲的设备文件 --- 显示器
全缓冲的设备文件 --- 磁盘文件
但所有的设备永远倾向于全缓冲 -- 缓冲区满了再刷新 -- 需要更少次数的IO操作 --更少次数的外设访问(相当于提高了整机效率).
有同学可能有疑问比如10行数据每一行有100个字节虽然10行最后再一起刷新只进行了一次的外设访问但是数据量很多啊1000个字节而按行刷新虽然刷新了10次但每次数据量少啊那为什么外设访问次数越少越好呢
这是因为和外部设备IO的时候数据量的大小不是主要矛盾你和外设预备IO的过程是最耗费时间的.
比如你和别人借钱往往沟通的过程要耗费很长时间而转账的过程只需要几秒这同样的道理.
那我们直接改成全缓冲不就行了吗这样效率不就高了吗还要什么行缓冲.
其实这些策略都是根据实际情况做的妥协
例如行缓冲就是针对于显示器是给用户看的一方面要照顾效率另一方面也要照顾用户体验.
而平常我们打开的一些文本文件便是全缓冲等到用户全部写完再一次性进行保存.
有了这些缓冲区和策略便可以提高数据处理的效率.
二、编写自己的fopen、fwrite、fclose
1.引入函数 这些函数都是3好手册的函数也就是说这些函数可以有2好手册的系统函数来封装。
2、引入FILE
在之前的语言学习时我们知道“-引用通常都是结构体那么stdin、stdout、stderr这三个流也就是结构体了。
因为IO相关函数与系统调用接口对应并且库函数封装系统调用所以本质上访问文件都是通过fd访 问的。
所以C库当中的FILE结构体内部必定封装了fd。
man 3 stdin我们可以看到他们的类型。
编辑
那么FILE又是什么类型呢
打开头文件找到EILE类 3.模拟封装
我们想要实现一个文件的打开写入和关闭文件操作的函数。
#includemyfile.h
#define myfile test.txt
int main()
{//打开文件_FILE* _fd _fopen(myfile,a);if(_fdNULL)return 1;//读文件const char*ptrhello linux!!\n;//size_t _fwrite(ptr,strlen(ptr),_fd);int cnt 10;while(cnt){_fwrite(ptr, strlen(ptr),_fd);// fflush(fp);sleep(1);cnt--;}//写关闭文件_fclose(_fd); return 0;
}
我们现在就来实现这个几个函数内部封装。
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdlib.h
#include unistd.h
#include assert.h#include string.h#define SIZE 1024
#define FILE_MODE 0666
#define FLUSH_NOW 1
#define FLUSH_LINE 2
#define FLUSH_ALL 4typedef struct _FILE_IO
{int fileno;int flag; //char inbuffer[SIZE];//int in_pos;char outbuffer[SIZE]; // 用一下这个int out_pos;
}_FILE;_FILE* _fopen(const char*path,const char* made);
size_t _fwrite(const char*ptr,size_t size,_FILE* _stream);
int _fclose(_FILE*_stream);1、fopen
_FILE* _fopen(const char*path,const char* made)
{assert(path);assert(made);int fd-1;int f0;if(strcmp(made, w) 0) {f (O_CREAT|O_WRONLY|O_TRUNC);fd open(path, f, FILE_MODE);}else if(strcmp(made, a) 0) {f (O_CREAT|O_WRONLY|O_APPEND);fd open(path, f, FILE_MODE);}else if(strcmp(made, r) 0) {f O_RDONLY;fd open(path, f);}else return NULL;if(fd -1) return NULL;_FILE *fp (_FILE*)malloc(sizeof(_FILE));if(fp NULL) return NULL;fp-fileno fd;//fp-flag FLUSH_LINE;fp-flag FLUSH_ALL;fp-out_pos 0;return fp;
}
2、fwrite
size_t _fwrite(const char*ptr,size_t size,_FILE* _stream)
{memcpy(_stream-outbuffer[_stream-out_pos], ptr, size); // 没有做异常处理, 也不考虑局部问题_stream-out_pos size;if(_stream-flagFLUSH_NOW){write(_stream-fileno, _stream-outbuffer, _stream-out_pos);_stream-out_pos 0;}else if(_stream-flagFLUSH_LINE){if(_stream-outbuffer[_stream-out_pos-1] \n){ // 不考虑其他情况write(_stream-fileno, _stream-outbuffer, _stream-out_pos);_stream-out_pos 0;}}else if(_stream-flag FLUSH_ALL){if(_stream-out_pos SIZE){write(_stream-fileno, _stream-outbuffer, _stream-out_pos);_stream-out_pos 0;}}return size;
}
3、fclose
int _fclose(_FILE*_stream)
{if(_stream NULL) return -1;int fd_stream-fileno;_fflush(_stream);close(fd);free(_stream);return fd;}
4、fflush
void _fflush(_FILE *fp)
{if(fp-out_pos 0){write(fp-fileno, fp-outbuffer, fp-out_pos);fp-out_pos 0;}
} 完整代码 总结
缓冲区位于用户程序和硬件设备之间用来缓存数据目的是让快速的 CPU 不必等待慢速的输入输出设备同时减少操作硬件的次数。对于 IO 密集型的网络应用程序如网站、数据库、DNS、CDN 等缓冲区的设计至关重要它能十倍甚至一百倍得提高程序性能。 关于缓冲区还有更多的内容将在 “文件操作” 一章中深入讲解