波奇学Linux:文件缓冲区

文章讨论了C语言中文件流输出到显示器和重定向到文件的不同,涉及到缓冲区策略(无缓冲、行缓冲、全缓冲),以及为何库函数(如printf)在不同情况下的输出差异。重点在于理解缓冲区刷新、write与内核交互以及exit和_exit函数的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题导入

文件流输出直接向显示器和重定向文件有不一样的表现

分别向显示器文件输出四个语句,最后fork创建子进程。

当程序运行时和程序重定向到文件中,输出的内容不一样。

重定向时c库函数(printf,fprintf,fwrite)调用了两次,而系统调用write函数只调用了一次

关闭对应的虚拟文件,只有系统调用可以输出

屏蔽系统调用,同时关闭显示器对应的虚拟文件

运行程序没有任何输出,只有系统调用有输出。如果先close(1)再系统调用也没有任何输出。

解释问题

问题二的解释

调用c的库函数是存在一个用户级别的缓冲区,当缓冲区的数据刷新时会把数据刷新到内核级别的缓冲区,而write函数可以直接把数据输入内核级别的缓冲区,而close的作用关闭fd为1虚拟文件。

相当于fprintf/printf和fwrite刷新不到内核级别的缓冲区了,而write可以直接写入。所以只有write的输出有结果。

那么就是说,只要把数据刷新到内核级别的缓冲区就能输入到显示器中。

目前我们认为,只要将数据刷新到内核,数据就可以刷新到硬件

用户级别缓冲区的刷新策略

无缓冲---直接刷新

行缓冲---缓冲区不刷新,直到碰到\n ---显示器

全缓冲---缓冲区写满才刷新---普通文件写入

进程退出也会刷新

显示器的文件的刷新方案是行刷新,所以printf执行完就立即遇到\n

因此我们只要加上\n让缓冲区立刻刷新,保证在close代码前就把数据刷新进入内核中,就能把信息输出到屏幕上。

所以在原代码中,库函数调用的语句都在缓冲区,没有立刻刷新,当进程退出时刷新缓冲区时,已经运行了close语句,此时缓冲区已经没办法找到内核了。

刷新的本质就是将数据通过fd=1+write接口写入到内核中.

有了以上铺垫我们就可以解释为什么库函数调用exit会刷新缓冲区,系统调用_exit不会刷新缓冲区

对于exit而言,他是包含用户级别的缓冲区而内核的,而_exit只知道内核,无法接触上一级的缓冲区也就无法刷新。

解释问题一

重定向意味着文件流是输入到普通文件,而不是显示器,是全缓冲策略。\n不会再刷新缓冲区,而是进程结束时刷新缓冲区。

而进程前运行fork函数,对数据进行写时拷贝。产生两个缓冲区。

注意write的输入不经过这个缓冲区,所以不会重复。

以fprintf举例。

缓冲区存在意义

体现封装的特性,对于库函数来说,不需要关注数据是如何刷新到硬件上的,只用把数据刷新到缓冲区即可

配合格式化,如将int型等都转换为字符串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值