初始linux之文件系统(下)

本文详细介绍了Linux中的缓冲区概念、刷新策略及其在内存与磁盘间的作用,揭示了缓冲区如何提高数据传输效率。接着,文章深入探讨了文件系统的逻辑结构,包括磁盘的物理结构、存储结构以及数据读取和管理逻辑,解释了如何通过分区、分组等方式高效管理大量数据。通过对inode、Block Bitmap、Group Descriptor Table等关键组件的解析,阐述了文件读取、删除的过程及文件与目录的关系。
摘要由CSDN通过智能技术生成

一、缓冲区

1.缓冲区的概念

我们以前一直在提缓冲区,但是缓冲区到底是什么,却并没有说过。其实缓冲区的本质,就是“一段内存”。既然缓冲区是一段内存,那么必定是有人申请的,是属于某个部分管理并且有自己的作用。

为了更好的理解缓冲区,我们来举一个例子:

假如你在四川,你有一个很好的朋友叫小王,他在上海的读书。你们平时关系非常的好,经常将自己的东西与对方分享。有一天你买了一个新的键盘,于是你就想以前旧的键盘送小王。刚好小王也想买一个键盘,于是此时你为了将东西送给他,就自己骑车从四川去往上海,亲手将东西送给了他。但是这这样反复了几次后,你觉得这样太费时间了,每次想送点东西给对方,都需要自己骑车几个月的送给小王。而此时你的室友看到了便告诉你,在我们宿舍里离宿舍不远出处有一个顺丰快递,你可以直接将快递交给顺丰,让他们帮你寄,只用一两天就可以到,省时省力

你一听,觉得这方法很好啊,于是将自己送给小王的礼物拿到了顺丰,让他们帮你寄。第二天你想去看看自己的礼物到哪里时,你发现自己的快递还没有出发,于是你又跑到顺丰,去质问工作人员,为什么一天了还没有发货。工作人员告诉你,他们的快递都是需要积累到一定数量,比如有个几十件几百件的时候才会统一开始运送,不会为你了这一件快递就帮你寄,毕竟一件一件的送太费成本。你听了后觉得有道理,就离开了。

在这个例子中,四川就是内存上海磁盘进程小王文件,你要寄的礼物数据,而顺丰则是缓冲区。你向小王赠送礼物这个动作,就可以看做是内存中的进程要向磁盘中的文件传输数据

我们以前也说过,磁盘的传输效率是很低的,当然,这个效率低是相对于内存而言。在这种情况下,如果我们一有数据就向缓冲区,就很可能因为磁盘读写速度太慢导致进程堵塞,传输效率下降。为了解决这一问题,便有了缓冲区的存在。当内存需要向磁盘读写数据时,会先将进程中对应的数据拷贝到缓冲区中,当缓冲区中的数据满足一定条件后,再统一将缓冲区内的数据刷新到磁盘中

此时大家就可能会有点疑惑,为什么是将进程中的数据拷贝到缓冲区中,我们明明一直是用write()、printf()、fputs()这些函数,并没有使用拷贝函数。这就涉及到一个理解上的问题。以fwrite()为例,与其将fwrite()函数理解为写数据到文件中的函数,不如将其理解为是将数据从进程中拷贝到缓冲区或外设中的一个拷贝函数。其他类似函数同理。因此,缓冲区存在的意义其实就是为了“节省进程进行数据IO的时间”

2.缓冲区刷新策略

缓冲区刷新的策略,一般都会根据不同的设备定制不同的刷新策略。而在通常情况下,会有三种刷新策略。而在某些特殊情况下,又会有两种特殊的刷新策略

(1)立即刷新——无缓冲

例如我们向磁盘里面写了一块数据,在写完后立即就调用了fflush()函数进行缓冲区刷新,此时就是立即刷新缓冲区

(2)行刷新——行缓冲

在某些情况下,例如我们的显示器,在显示东西时,为了适应人一行阅读的阅读习惯,就会才采取行刷新的刷新策略,这样就既可以适应人的阅读习惯,又不至于刷新效率太低。

(3)缓冲区满——全缓冲

为了利用好缓冲区,我们还有一种全缓冲的刷新策略,即当缓冲区满了的时候,才会将数据刷新出来。例如我们打开我们的磁盘文件时,都是直接显示完或者一片一片的显示,这其实就是全缓冲刷新策略导致的。

(4)用户强制刷新

某些情况下,用户可能会想在缓冲区未满的情况下就将缓冲区内的数据刷新出来,如调用fflush(),此时就是用户自行进行强制刷新

(5)进程退出

在进程退出时,也会将缓冲区内的数据刷新出来,避免进程退出了但缓冲区还没满,导致缓冲区内的数据没刷新出来进而出现数据丢失的情况

3.缓冲区存在位置

现在我们知道了缓冲区的本质其实就是“一块内存”,并且在不同情况下有不同的刷新策略,但是却并不知道缓冲区到底在哪里。

由此,我们先来看以下代码:

在上面的程序中,我们分别以C和系统接口的方式,向stdout打印和写数据。我们运行该程序:

可以看到,运行正常。然后我们再将该程序的结果重定向到“log.txt”文件中并打开该文件:

此时得到的结果也是正常的。此时我们修改该程序,在程序结束之前创建一个“子进程”

我们运行该程序:

此时该程序运行结果没有任何问题。但是,此时我们再将该程序的结果重定向到“log.txt”文件中:

可以看到,此时该文件中出现了7条打印结果,其中用C接口写的打印和输出函数打印了两次。但是用系统借口写的write()函数却并没有重复打印

导致这一结果产生的原因,肯定是“缓冲区”的存在。

但是既然缓冲区存在,那为什么在上面的程序中,C接口的打印重复了两次,而系统接口的write却没有重复呢?通过这一现象我们其实可以得到一个结论:这里的缓冲区其实是由C提供的。也就是说,缓冲区其实是用户级语言层面给我们提供的。因为如果这一内存存在于内核中,那么write()也应该重复打印。

现在我们知道了缓冲区是由用户级语言提供的。但是它们到底存在于哪里我们还不清楚。以C为例,我们无论是进行printf()还是fprintf(),都会显式或隐式的涉及到stdin、stdout和stderr这三个标准流。在使用时,我们都会传入一个“FILE*”指针。而FILE我们之前也也说过,它其实是一个“FILE结构体”,其中一定包括了文件描述符fd,其实这里面还一定存在一个东西,即缓冲区

因此,我们在使用fflush()或fclose()时,都需要传入一个文件指针,这其实就是为了使用缓冲区。

我们可以在linux中打开“libio.h”头文件查看:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值