文件缓冲区


一、Linux下一切皆文件

所有操作计算机的动作都是以进程操作的,访问文件都是以进程方式完成,进程是操作系统帮助用户完成任务的渠道之一,给进程分派各种任务让进程去完成。目前所有对文件的访问都是以进程为载体。在操作系统中存在各种设备(大部分是外设),但是这么多外设,如磁盘和显示器不一样为什么会是一切皆文件?因为每一种设备都有结构体描述对应设备的信息(而在每一种设备上有对应的读写方法,而对文件的操作就是读写操作)设备以文件的方式以open打开,而打开的文件在linux内核中会创建struct file文件对象,Linux内核中提供了一种结构,提供了一张方法表,对于每一个打开的文件会创建一个方法表对象,操作系统设计系统调用让用户统一使用一个系统调用访问设备,访问那些设备就是以一个统一的系统接口来访问,上层封装了read和write对设备进行读写操作这也就是实现了一切皆文件!
在这里插入图片描述

二、缓冲区

在这里插入图片描述
正常打印结果
把显示器文件关了之后write再向显示器文件中写,就无法写入进去
在这里插入图片描述
fork创建子进程,执行时看不出区别
在这里插入图片描述
将可执行文件重定向到普通文件中
在这里插入图片描述

但是当将可执行文件内容重定向到普通文件中时,此时显示内容为c库函数的内容打印了两份,然后系统调用接口write打印了一次,这是为什么?并且系统调用接口的内容出现在了最前面。
当各种函数所打印的内容不带\n时,出现现象如下
在这里插入图片描述
同样是系统调用接口先显示出来,然后再是库函数的内容显示出来
以上的现象如何解释?以上有些内容并没有立即显示出来,反而是等到最后再显示出来,就像是首先储存在了一个地方,然后是等到合适的时机再从这个地方拿出来!这样的储存地方为缓冲区,输入的内容并没有立即打印到显示器文件中,而是先将输入的内容储存到一个缓冲区,等到合适的时机,将缓冲区中的内容刷新到操作系统内部,c库函数接口是按照行刷新的规则进行将缓冲区的内容进行刷新,缓冲区中的数据不会被立即刷新!c库函数对于内容显示到显示器上的刷新策略是行刷新,而对于显示到普通文件中是全刷新策略。c语言提供的缓冲区不在内核中,它是一个用户级缓冲区。c库只是暂时将数据储存到缓冲区中,等到合适的时机再调用系统接口写入到操作系统中,而若是直接将这个文件关掉则还没有将数据写到操作系统所有就不会将数据打印出来!缓冲区的刷新就像是一个快递站,快递站堆积的快递个数,可以是一个货架堆积满了之后将这些快递发往下一个快递点,或者就是整个仓库堆积满再发往下一个快递点,但是整个仓库堆积对于使用的人来说可能会导致效率低下,但是对于快递点来说不用多次反而含还提高了效率!不同的需求有不同的刷新策略。刷新的本质就是刷到下一个地点,而显示器刷新的本质就是将数据通过调用write写入到内核中。
exit和_exit
exit在退出进程时会将进程的缓冲区做刷新动作,将缓冲区的内容全部刷新出来exit->fflush->_exit
_exit在退出进程时是直接退出一个进程不会对进程的缓冲区做刷新动作

一般C库函数写入文件时是全缓冲的,而写入显示器是行缓冲。
printf fwrite 库函数会自带缓冲区(进度条例子就可以说明),当发生重定向到普通文件时,数据的缓冲方式由行缓冲变成了全缓冲。
而我们放在缓冲区中的数据,就不会被立即刷新,甚至fork之后但是进程退出之后,会统一刷新,写入文件当中。但是fork的时候,父子数据会发生写时拷贝,所以当你父进程准备刷新的时候,子进程也就有了同样的一份数据,随即产生两份数据。write 没有变化,说明没有所谓的缓冲
综上: printf fwrite 库函数会自带缓冲区,而 write 系统调用没有带缓冲区。另外,我们这里所说的缓冲区,都是用户级缓冲区。其实为了提升整机性能,OS也会提供相关内核级缓冲区,那这个缓冲区谁提供呢? printf fwrite 是库函数, write 是系统调用,库函数在系统调用的“上层”, 是对系统调用的“封装”,但是 write 没有缓冲区,而 printf fwrite 有,足以说明,该缓冲区是二次加上的,又因为是C,所以由C标准库提供。
缓冲区在哪?
进程打开文件注定会存在多个被打开的文件,而这些被打开的文件操作系统要将其进行管理,用struct FILE结构体进行管理,一个个FILE对象,在FILE结构体中有打开文件的缓冲区字段和维护信息,它是在FILE对象中,而FILE对象是属于用户的所以这个缓冲区是用户及缓冲区,一个文件有一个缓冲区,每一个打开的文件都有自己的缓冲区。

三、缓冲区刷新策略

printf写数据到了缓冲区缓冲区的刷新策略是什么?
1.无缓冲:就是不在缓冲区中做任何的残留,而是直接将数据刷新,调用库函数之后直接调用fflush进行刷新。
2.行缓冲:当写入一个数据时缓冲区不会立即刷新,而是碰到\n再进行刷新缓冲区,而刷新是将\n之前的所有数据都刷新出去
3.全缓冲:就是缓冲区没有写满不会刷新,要等到满了再刷新(向普通文件中写入时)文件的内容不需要用户来看,运用全缓冲提高效率,减少刷新次数。还有就是再进程退出时也会将缓冲区的数据全部进行刷新

  • 40
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值