【Linux】—— Linux下的文件缓冲区

缓冲区机制

根据应用程序对文件的访问方式,即是否存在缓冲区,对文件的访问可以分为带缓冲区的操作和非缓冲区的文件操作:

  • a)带缓冲区文件操作:高级标准文件I/O操作(eg:C库定义的fwrite和fread已经printf函数),将会在用户空间中自动为正在使用的文件开辟内存缓冲区。

  • b)非缓冲区文件操作:低级文件I/O操作(eg:系统接口read和write),读写文件时,不会开辟对文件操作的缓冲区,直接通过系统调用对磁盘进行操作(读、写等),当然用于可以在自己的程序中为每个文件设定缓冲区。

缓冲类型

标准I/O提供了3种类型的缓冲区。

  • 1、全缓冲区:这种缓冲方式要求填满整个缓冲区后才进行I/O系统调用操作。对于磁盘文件的操作通常使用全缓冲的方式访问。第一次执行I/O操作时,ANSI标准的文件管理函数通过调用malloc函数获得需要使用的缓冲区,默认大小为8192。
  • 2、行缓存区:在这种情况下,当在输入和输出中遇到换行符时,标准I/O库函数将会执行系统调用操作。当所操作的流涉及一个终端时(例如标准输入和标准输出),使用行缓冲方式。因为标准I/O库每行的缓冲区长度是固定的,所以只要填满了缓冲区,即使还没有遇到换行符,也会执行I/O系统调用操作,默认行缓冲区的大小为1024。
  • 3、 无缓冲区:无缓冲区是指标准I/O库不对字符进行缓存,直接调用系统调用。标准出错流stderr通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。

缓冲区存在的意义

主要的意义就是为了提高cpu的效率。

  • 输入端。假如没有缓冲区,我们要从磁盘中读取数据,有几个字符,CPU就要读写几次,CPU是高速率的,而读取是低速率的,这样做会降低CPU的效率。相反如果将数据都存在缓冲区里面,等要读取的时候就可以一次性读取多数的数据。大大地提高了CPU的效率。
  • 输出端。假如要将数据打印出来,打印机是低速的,CPU是高速的。将数据放入缓冲区,避免数据被分为多次打印,就此解放了CPU,使它能去处理其他任务。

了解了以上知识点之后我们来看一段代码:

#include <stdio.h>
#include <string.h>
int main()
{
 	const char *msg0="hello printf\n";
 	const char *msg1="hello fwrite\n";
	const char *msg2="hello write\n";
	 
	 printf("%s", msg0);
	 fwrite(msg1, strlen(msg0), 1, stdout);
	 write(1, msg2, strlen(msg2));
	
	 fork();
 	
 	return 0;
}

程序运行结果:
file
但是如果我们将程序运行结果重定向到我们自己创建的文件myfile中,看结果:
file
我们可以发现printf和fwrite(库函数)都输出了两次,而write(系统调用)只输出了一次,为什么呢,我们可以知道肯定与fork()有关,但具体有什么关系,我们来解释一下:

  • 首先我们之前介绍了存在3种缓冲类型,分别是全缓冲,行缓冲,无缓冲。
  • 一般C库函数写入文件时都是属于全缓冲的,而写入显示器属于行缓冲。
  • printf和fwrite是属于C库函数,是自带缓冲区的,当他们的输出被重定向入普通文件时,数据的缓冲区由行缓冲变为全缓冲。
  • 之前我们也提过,全缓冲模式中的数据不会立即刷新,而是在缓冲区满了之后才会刷新,因此在fork函数之后都不会刷新数据,依旧存放在缓冲区中。
  • 但是fork函数之后,创建了子进程,父子进程的数据会发生写时拷贝,所以当父进程准备刷新数据时,此时发生写时拷贝,子进程也会拷贝一份父进程缓冲区中的数据,随着缓冲区刷新,父子进程分别打印出一份数据,于是有了两份数据。
  • write没有变化,说明write不存在缓冲区,属于系统调用
综上所述: printf fwrite 库函数会自带缓冲区,而 write 系统调用没有带缓冲区。另外,我们这里所说的缓冲区,都是用户级缓冲区。其实为了提升整机性能,OS也会提供相关内核级缓冲区,不过不再我们讨论范围之内。那这个缓冲区谁提供呢? printf fwrite 是库函数, write 是系统调用,库函数在系统调用的“上层”, 是对系统调用的“封装”,但是 write 没有缓冲区,而 printf fwrite 有,足以说明,该缓冲区是二次加上的,又因为是C,所以由C标准库提供。

计算机系统组成

发布了167 篇原创文章 · 获赞 175 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chenxiyuehh/article/details/90577631
今日推荐