引言:
是什么?
从最简单的理解方面来,我们可以将缓冲区理解成一块内存!那么这块内存是从哪里来的呢?在linux中一般我们所说的缓冲区都是由C提供的语言级别的缓冲区!
干什么的?
那么缓冲区的作用主要是用来干什么的呢?可以从我们生活中的例子来理解!假设你的朋友小张下个月就要过生日了,你要送他一个生日礼物!但是你们两个距离很远!一个在西藏,一个在海南!如果让你自行将生日礼物送给他,那么无疑将会浪费你的很多成本!但是现实中存在快递站,只需要你下楼将礼物交付给快递站,然后由快递站代替你送过去即可!那么在本例子内,快递站的作用就是一个缓冲区的作用!
为什么要存在缓冲区?
根据上面提到的例子,很容易理解,因为有了快递站的存在,使我们方便了很多!所以类似于此,缓冲区存在的意义就是为了提高效率,减少我们的成本!
下面通过一段代码来证明一下缓冲区确实存在!
我们用户通常写程序在屏幕上打印一段文字的时候!其中就利用到了缓冲区!例如下面这个例子!
运行这段程序之后,显示屏上并没没有立刻打印出“hello linux”,这是为什么呢?根据我们所了解到的知识,程序是自上向下运行的,运行到sleep的时候,printf语句一定是执行过了,但是为什么没有打印出结果呢?根据此例子可以充分的证明缓冲区的存在!!既然证明了缓冲区的存在,那么我们将来一步一步的进行分析缓冲区的相关知识1
那么从系统角度来将该如何理解的呢?
从操作系统角度上来看!用户输入一段指令,该指令并没有直接传递到内核文件内存中!而是将用户输入的指令存放到了C提供的语言级别的缓冲区内!然后在C语言的缓冲区中经过刷新之后!再传递到内核结构中的文件缓冲区中!最后系统会定期的将内存的数据刷新到磁盘中!此阶段也可以称之为刷新!在此,我们提到了两个缓冲区,一个是用户层的C语言提供的语言级别的缓冲区,一个是内核结构中的内核文件缓冲区!一般我们所考虑的都是C语言提供的语言级别的缓冲区!
缓冲区的一些特性:
根据缓冲区能够存储一定的数据可以推出:缓冲区一定存在着刷新的方式!
1.无缓冲(立即刷新!)
2.行缓冲(行刷新!)
一般对于显示器文件,都是基于行缓冲的模式!
3.全缓冲(存放满然后进行刷新!)
对于磁盘文件,都是基于全缓冲的方式!
那么根据以上的特征,缓冲区也会有着特殊的情况!
1.强制刷新!
2.进程退出后,会自动进行刷新!(无论是否满足刷新的条件!)
实例:充分理解缓冲区
下面通过一段代码来充分理解缓冲区中的行缓冲和全缓冲!
上面代码运行过后,每行代码都打印了出来!这是为什么呢?刚才不是还说是存在缓冲区的么?其实不难理解,因为每段代码都有了\n换行符,强制让缓冲区内的数据进行刷新!所以数据都原样的打印了出来!!
那么将上面的代码经过简单的修改就会出现另外一种结果!
经过上面代码简单的修改,我们发现C函数的调用都打印了两次,而是用系统调用的write确只调用了一次!这是为什么呢?其实很简单!
我们可以看出,我们将输出结果由原来的行缓冲转化成了全缓冲(因为将结果打印到了log.txt文本文件中,文本文档默认为全缓冲的刷新方式!)所以只有当将缓冲区填满的时候,才会进行刷新!才能打印到显示屏中!又因为调用了fork函数,创建了新的子进程!根据fork的特性会继承父进程的代码和数据块!因为此时代码仍然在缓冲区内!所以子进程也会继承这些相同的代码和数据块!然后当一个进程结束后,就会发生写时拷贝!这是因为当一个进程退出的时候,一般都会对缓冲区的数据进行刷新,那么算不算清空或写入的操作呢?答案是肯定的!当时算!所以就会发生写时拷贝!所以可以推出,一旦一个进程退出,那么就会发生写时拷贝!
根据上图结果看出,系统调用write只打印了一次!从这里可以推出:write没用使用C语言的缓冲区!因为C语言的一些函数,大多都是对系统调用的封装!大多都是因为封装的原因!而导致他们使用C提供的缓冲区!而系统调用处于内核级别,在用户级别的下面,直接将数据写入到内核文件系统中!所以不使用C提供的缓冲区!
实例中的主要知识点:
1.当我们直接向显示器打印的时候,显示器文件的刷新方式是行刷新!而是我们的代码输出的所有字符串,都有\n,fork之前,数据已经全部被刷新!包括systemcall!
2.重定向到log.txt之后,本质是向磁盘文件中写入(而不再是显示器里面!),我们系统对于数据的刷新方式已经由行刷新转化到了全刷新的方式!变成了全缓冲!
3.全缓冲意味着缓冲区变大,实际写入的简单数据,不足以将缓冲区填满!fork执行的时候,数据依然在缓冲区内部!
4.我们目前所谈的缓冲区,是和操作系统没有关系的!只能和C语言本身有关!!
5.C/C++提供的缓冲区,里面保存的一定是用户的数据!其属于当前进程运行的数据!但是如果当把数据交付给OS,这些数据就属于OS了,不再属于该进程了!
6.当进程退出的时候,一般会进行刷新缓冲区,即使我们的数据没有满足刷新条件!
证明缓冲区的存在以及其在内核中的结构!
既然我们都讲了这么多关于缓冲区的知识了,那么我们确实已经知道了缓冲区真实存在!那么能否让我看一看其到底是什么样子的呢?
通过以上函数,我们可以发现,大多的输入输出操作,以及文件的操作都用到了FILE该结构体!那么该结构体之中我们之前知道其包含了文件描述符fd,那么其是否介意再包含一个缓冲区的成员变量呢?答案是当然不介意的啦!
我们可以通过对FILE的观察来看一下缓冲区的真实存在!
我们通过grep指令来查看FILE的路径!然后在FILE内部继续进行查找,最后看到FILE内部有我们熟悉的文件描述符_fileno,以及我们今天所讲的缓冲区的内容!
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
添加我为好友,拉您入交流群!
请使用微信扫一扫!