【Linux】文件缓冲区|理解文件系统

目录

预备知识

观察现象

第一:携带\n,不使用fork(),打印到显示器

第二:携带\n,使用fork(),打印到显示器

第三:携带\n,使用fork(),打印到文件里

第四:不携带\n,使用fork(),打印到显示器

解释现象

   携带\n,不使用fork(),打印到显示器 -- 解释

携带\n,使用fork(),打印到显示器 -- 解释

携带\n,使用fork(),打印到文件中 -- 解释


预备知识

有三种缓冲方式:全缓冲、行缓冲和无缓冲。

全缓冲(Fully Buffered):数据写入到缓冲区中,当缓冲区被填满或者达到一定条件时,才会刷新缓冲区。当内容写入到文件中时,也使用无缓冲。

行缓冲(Line Buffered):每当遇到换行符的时候,缓冲区就会刷新,将内容写入到文件中。

无缓冲(Unbuffered)数据直接刷新,写多少刷新多少。

观察现象

第一:携带\n,不使用fork(),打印到显示器

第二:携带\n,使用fork(),打印到显示器

第三:携带\n,使用fork(),打印到文件里

第四:不携带\n,使用fork(),打印到显示器

解释现象

如上图所示,C语言自己为自己提供了一个缓冲区,这个是用户级缓冲区。

操作系统在内核中也提供了一个缓冲区,这个是系统缓冲区。

为什么C语言要自己提供一个缓冲区,直接用系统的不就好了吗?

因为直接每次都进行实际的I/O操作(如磁盘读写、网络传输)可能会导致性能下降,因此引入缓冲区可以减少实际I/O操作的次数,提高程序的执行效率

具体来说:

  1. 性能优化:使用缓冲区可以减少系统调用的次数,避免频繁的I/O操作,从而提高程序的性能和效率。将数据暂时存储在缓冲区中,一次性地进行输出,比多次逐个字符地输出要更快。

  2. 灵活性:C语言为程序员提供了对缓冲区的控制权,可以手动刷新缓冲区、设置缓冲区大小等,使得程序在不同场景下能够灵活地进行优化。

  3. 错误处理:使用缓冲区可以使得程序更容易进行错误处理。在数据写入缓冲区时,程序可以检查写入是否成功、缓冲区是否溢出等,从而更好地处理可能出现的错误情况。 

   携带\n,不使用fork(),打印到显示器 -- 解释

当我们使用C语言的接口时,例如:printf/fprintf/fwrite等函数时,写入的内容会暂时放入到用户级缓冲区中。

正如之前所说,打印到显示器中时使用的是行缓冲,如果遇到\n,就会立即刷新。

所以在“携带\n,不使用fork(),打印到显示器”中时,才会C语言调用接口和系统调用接口都只打印一次。因为是行缓冲,每句语句到最后都直接刷新打印了,不会有延时。

携带\n,使用fork(),打印到显示器 -- 解释

“携带\n,使用fork(),打印到显示器”中时,C语言的接口打印一次,系统调用接口也打印一次。因为携带了\n,是行缓冲,任何一个语句写入到缓冲区,因为最后携带了\n,所以在下一个语句到缓冲区的时候,前面的会被刷新出去。所以在最后fork()的时候,子进程拷贝了父进程的数据和代码,但是父进程的缓冲区是空的,所以子进程的缓冲区也是空的,所以只打印一次。write()函数是系统调用,直接放入到系统的缓冲区,所以不受影响。

具体情况如下所示:

重定向:刷新方式发生更改,

数据写入时,由刷新改为暂存

携带\n,使用fork(),打印到文件中 -- 解释

在“携带\n,用fork(),打印到文件中”时,C式接口打印两次,系统调用接口打印一次。因为打印到文件中时,缓冲方式由行缓冲转换为全缓冲。所以父进程中就会把C式接口中的内容全部放入到C语言的缓冲区中,当使用fork的时候,子进程拷贝父进程的内容,也会拷贝父进程的缓冲区。当程序结束,要刷新缓冲区。刷新缓冲区的本质就是写入,就会发生写时拷贝,所以到系统缓冲区时,C式的接口就会打印两次,系统调用接口不受影响。

过程如图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值