前言
一、缓冲区
缓冲区的作用是提高效率,因为将数据写入到设备,是需要调用系统接口的,如果每次写入缓冲区的数据就调用一次系统调用,涉及到系统调用这时操作系统就会介入,用户态转为内核态,这个过程需要时间,效率比较低。有了缓冲区,满足一定条件才会调用系统调用将数据统写入到操作系统而不用频繁的调用系统接口。刷新:其实就是将用户缓冲区的数据写入操作系统的过程。
1.缓冲区的刷新策略:
(1)无缓冲也就是立即刷新
(2)行缓冲(行刷新,比如显示器的文件)
(3)全缓冲(缓冲区满了,再刷新,比如磁盘上的文件)
特殊情况:
(1)强制刷新,比如c语言fllush函数
(2)进程退出时,一般要进行刷新
2.行缓冲和全缓冲
验证:
(1)行刷新,遇到\n就刷新。
(2)如果重定向到普通文件就是全缓冲,当写满或者强制刷新才会刷新到操作系统。
这里我们解释一下,由于缓冲区的数据属于进程,第一个程序中,是行刷新遇到\n,数据已经刷新到操作系统了,缓冲区已经清空。第二个是由于行缓冲没有遇到\n就没有刷新,缓冲区的数据还在,创建子进程,一方发生写入时就会写实拷贝,由于进程退出就会刷新,于是就打印两份。第三个是由于文件的重定向,输出定向到文件已经是全缓冲了,数据还在缓冲区中,创建子进程,一方发生写入时,写实拷贝,于是也打印了两份。
当是我们发现一个问题,这个调用系统调用(write).写入数据时,不管有没有刷新,它都是一份数据。因为这个系统调用是直接将数据写入操作系统,和进程中c语言提供的缓冲区没有任何关系。刷新的过程就是调用这个接口。
类似于这个,对于不同的文件它都有一个c语言提供的缓冲区,它们之间是互不影响。
3.C库的原理实现:
C语言的文件的打开和关闭,读写,都是系统调用的封装。比如,c语言将输入流(stdin)和输出流(stdout),还有错误流(stderr)封装为一个结构体,C语言提供的缓冲区类似于字符数组,其实就是结构体中指向一段开辟的空间,C语言通过封装系统调用来提供了一套方便的文件操作接口。这些接口允许用户以高级的方式(如通过文件流和缓冲区)来操作文件,而无需直接处理底层的系统调用和内存管理。