为什么要有文件缓冲区的存在?
假设甲在云南,甲的朋友乙在北京,甲想给乙送个东西就需要跑到北京去:这时候有菜鸟驿站了,甲就不用跑了,直接把包裹交给菜鸟驿站就可以了。缓冲区就类似于菜鸟驿站,缓冲区可以提高使用者的效率。
菜鸟不会因为你一个包裹就专门送一趟,而是一次性送大量包裹,这样可以节约成本。缓冲区也是如此,正是因为有缓冲区,才可以积累一部分在统一发送,可以提高发送的效率。
菜鸟会给不同日期的包裹分组,按组发货。缓冲区也是如此,有不同的刷新方式。
大致分为以下几种普通情况:
普通情况
1.无缓冲(立即刷新)
2.行缓冲(行刷新)
3.全缓冲(缓冲区满了,再刷新)
特殊情况
1.菜鸟为了节约成本采用全缓冲,等仓库满了才发货,但是这样太慢了,收到了用户的投诉,要求立刻发货,这个就称之为强制刷新。
2.菜鸟倒闭了,但是要在关门之前把所有仓库里的存货全部发出,这个叫做在进程结束前刷新。
实验1
在实现进行之前,我们需要了解两个常识:
1.在显示器中一般采用行刷新
2.对于磁盘文件一般采用全刷新。
实验开始。
我们写一段代码,通过printf,fputs,fprintf,write,向显示器打印一些内容:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
fprintf(stdout,"c:hello fprintf\n");
printf("c:hello printf\n");
fputs("c:hello fputs\n",stdout);
const char *str="system call:hello wirte\n";
write(1,str,strlen(str));
return 0;
}
fprintf和printf,fputs都为c语言接口,其中fprintf和puts都需要显式指示向哪个流输出,printf是隐式的。write是系统调用接口。
现在我们加一句代码:
我们发现一个现象,将输出重定向到log.txt之后c语言的一共打印了七次,其中c语言的调用每个都打印了两次,系统调用的接口只打印了1次。
我们都知道fork()之后父子进程共享,所以这里如果fork()在最前面,那么可以理解后面为什么每个输出都输出两次。但是这里fork()在最后面,为什么每个输出还会每个输出两次呢?
原因
因为向显示器输出是按行刷新的,文件重定向之后向log.txt文件输出,log.txt属于磁盘文件,磁盘文件是全刷新,读入的内容不足以把缓冲区写满,在执行fork的时候,缓冲区还没有满,没有刷新,执行完fork之后因为进行要结束了,即便此时不满足刷新条件,但是进程结束时还是要把缓冲区里面的内容刷新。
但是我们发现,系统调用接口并没有受影响,还是只打印了一次,因此我们可以确定,缓冲区是和操作系统没有关系的。
总结:我们日常用的缓冲区由c语言提供,和操作系统没有关系,称为语言级别缓冲区。