[Linux]——文件缓冲区

文件缓冲区

提到文件缓冲区这个概念我们好像并不陌生,但是我们对于这个概念好像又是模糊的存在脑海中,之间我们在介绍c语言文件操作已经简单的提过这个概念,今天我们不妨深入理解什么是文件缓冲区。

为什么需要文件缓冲区

当我们在程序中写下一条printf语句时,我们希望将这条语句的内容打印到屏幕上。但是如果你将语句放在循环中,难道你执行一次循环那么操作系统就要打印一次这条数据么?答案当然不是

我们对于程序数据和磁盘数据的交换的时候不是直接进行交换的,他们之间存在了一个数据缓冲区,只有缓冲区中的数据达到某种条件时,相应的对象才会对缓冲区中的数据进行操作

在这里插入图片描述

证明存在输入缓冲区

下面这段代码很多朋友可能不知道,当你输入一串字符串,假设输入abcdef时,一个回车,你以为接下来要确定输入Y/N时这个代码实际直接结束了,他跳过了输入这个字符的环节(感兴趣的同学试一试)

int main()//验证输入缓冲区
{
	int ch;
	char arr[10] = { 0 };
	printf("请输入密码\n");
	scanf("%s", arr);
	printf("请确认密码(Y/N)\n");	
	ch = getchar();
	if (ch == 'Y')
	{
		printf("y");
	}
	else
	{
		printf("n");
	}
	system("pause");
	return 0;
}

为什么呢?让我来告诉你
在这里插入图片描述
那我们有没有解决这个bug的方案呢?有,在vs2008下我们可以使用fflush函数来清空输入缓冲区,但是这个函数在高级编译器(vs2013)以后就禁止使用了。但我们可以自己清空缓冲区

while (getchar() != '\n')//在getchar()之前获取完缓冲区中所有的字符
{
	;
}

证明存在输出缓冲区

此代码必须在Linux下验证
如下代码很多同学以为会每秒输出一个a,但是事实上他输出一个后就不在输出了,这其实也就证明输出缓冲区是存在的,只有当缓冲区的数据满时,他才会一次性打印在屏幕上。

int main()
{
	while (1)
	{
		printf("a");
		Sleep(1);//linux下停止1s
	}
	return 0;
}

数据缓冲的方式

我们现在已经证明了确实是有数据缓冲区的存在的,那么数据的缓冲方式到底有哪些呢?

  • 无缓冲:无缓冲的意思是说,直接对数据进行操作,无需经过数据缓冲区缓存,系统调用接口采用此方式
  • 行缓存:缓冲区的数据每满一行即对数据进行操作,而通常情况下向屏幕打印数据就是行缓存方式
  • 全缓冲:缓冲区的数据满时才对数据进行操作,通常向文件中写数据使用的就是全缓冲方式

现在我们来证明这几种数据的缓冲方式:

分别使用printf和write向屏幕打印数据。
在这里插入图片描述
想屏幕打印数据:没问题
在这里插入图片描述
重定向到文件中:也拿到了我们想要的结果
在这里插入图片描述

现在来看看如何证明缓冲区的三种方式

修改代码,给函数的最末尾加了一句fork

在这里插入图片描述
打印到屏幕:
在这里插入图片描述
重定向到文件:奇怪的现象出现了,文件里居然有两个hello printf
在这里插入图片描述

现在我们来说说这两种不同的现象吧:

  • 打印到屏幕:因为write是系统调用函数,无缓冲打印数据,printf是行缓冲打印数据,所以将数据打印到屏幕上再调用fork(其实就是fork没起到作用)是我们预料到的
  • 重定向到文件:为什么文件中出现了两次hello printf?首先我们要知道向文件写数据是全缓冲,但是write同样是无缓冲,所以直接写入到文件中,printf打印的数据先被放到了缓冲区中,此时我们调用了子进程,子进程对父进程的数据进行了写时拷贝,对缓冲区中的数据多操作了一次,所以我们发现此时文件中的hello printf就有了两份

缓冲区的本质

经过上面的例子,我们实际上还要明白一点,实际上缓冲区这个概念是c语言提供给我们的,我们所调用的系统调用函数其实并不存在缓冲区,缓冲区就是本质上就是一段内存,至于怎么找到这段内存,也就是找到缓冲区,还记得我们描述文件的file结构体么?
在这里插入图片描述
也就是说,通过file结构体,我们也就能找到文件相对应的缓冲区了。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值