0


初识Linux · 文件系统


前言:

前文我们介绍了磁盘,介绍磁盘的原因是因为我们需要在理解文件系统之前,通过磁盘的了解,介绍一些文件相关的内容,比如文件是如何在磁盘里面存储的,什么是CHS定址法,为什么OS不使用CHS定址法,什么是LBA块等。

我们今天的介绍顺序是,先简单搭建起来对文件系统的理解,再深挖细节问题。

那么,进入今日的话题吧!


简单理解文件系统

对于文件系统框架的搭建,我们可以先从这个指令进入:

即stat指令,查看文件的信息,这个信息,是文件的属性?还是文件的内容呢?

我们知道文件 = 属性 + 内容,但是我们常常关注的都是文件的内容,对于文件的属性我们关注的并没有那么常见。所以要理解文件系统的框架,我们要从文件的属性进入。

由stat提供的信息来看,我们看到了File:main.c,这个代表的是文件名,Size代表的是文件的大小,Blocks?IO Block? Inode?这些都是什么?

不急,我们再次引入上文的话题:

对于上文,将磁盘从非线性的转换为了线性的,然后线性的空间我们看成了数组,那么数组,我们可以通过位图的类似做法,找到数据的存储地址。但是因为磁盘取数据的特殊点,取数据都是一次性的取4kb数据,所以OS为了方便将数据分为了多个块,也就是LBA块,分好之后,找到一整块空间就十分容易了。

所以我们对于文件的管理从磁盘,到了CHS,到了数组,到了LBA,最后无非就是搞清楚LBA里面究竟有什么就可以了:

形象的图片就是这样,那么块组里面,我们分清楚了有Super Block, Group Deseciptor Table, Block Bitmap, Inode Table, Data Blocks。

那么我们从哪里开始讨论呢?

从Data Blocks开始讨论:Data Blocks是数据块的翻译,也就是文件的内容都是放在这里的,但是因为方便介绍,我们将Data Blocks的大小缩小成了和其他差不多的大小。对于该块,占据的空间大小应该是整个块组的95%以上。

那么对于Data Blocks里面都有什么呢?

看起来是非常抽象的,因为Data Blocks里面存储的都是一个一个的数据块,大小都是为4kb的,取的时候就直接将该数据块丢出去就行了。

对于这么多的数据块,都是只存储文件的内容的

并且,我们知道,文件 = 内容 + 属性,对于文件内容属性而言,Linux特定的文件系统是将文件的属性和内容分开存储的,这点我们先记住。对于Data Blocks我们就探讨到这里。

那么下一个,就是Block Bitmap,相信在C++学习的时候,同学们都是知道位图这个概念的。

最开始介绍位图的时候,都是通过的判断数据是否在一堆数据的集合里面,这里同理,引入block Bitmap就是为了判断是否某个数据块是否存在数据,这里位图就不多介绍了,但是引入了位图,确实能在遍历数据块上节省极大部分的时间。


下一个就是非常重要的inode Table,inode Table成为i节点表,存放的是文件的属性,文件的大小,所有者,最近的修改时间等。这是inode Table。

那么文件的属性一般都有什么呢?

struct inode
{
    int size;
    mode_t mode;
    int creater;
    int time;
    ...
    int inode_number;
    int datablocks[N];
};

我们拿几个非常常见的出来举例,文件大小,文件的权限,创建时间等,但是最重要的,我们应该关心inode_number和datablocks[N]。而这个块的名字是inode_table,所以它所处的空间自然是这么多个结构体所处的集合。

所以!!文件的属性不过是一个一个完全相同的结构体!!

而在里面,inode的结构体如何分区的呢,都是通过inode_number进行分区的,那么datablocks的作用是什么呢?我们使用文件的时候,通过了inode_number找到了对应的文件属性结构体,我们需要找到内容,就需要datablocks,这个数据指向的内容就是block Data的空间:

像这样,比如N等于12的时候,前11个直接指向的数据块,但是我们没有办法找到对应的大文件,所以第12个,指向的Data Blocks里面也存放的指针,指向了其他的数据块,就有一种指数的感觉。

那么数据还不够,13 14后面都可以指向,并且就不是一层关系这么简单了,是一层指向一层,一层又指向一层,套好几层最后才指向数据,这样就能找到大文件的数据了。

这种查找数据的方法叫做ext2文件系统,我们目前大多数使用的都是ext2,还有ext3 ext4等。

所以对于inode结构体我们就知道了个所以然,那么inode bitmap?那不就是同理了吗!!

通过inode bitmap找到表里面的某个位置是否存在文件的属性,然后进行后续的操作。


那么现在,我们就清楚了inode table, inode bitmap, data blocks, data bitmap。对于剩下的两个,比如GDT,也就是Group Descriptor table,翻译过来叫做块组描述符,描述的是块组的属性信息,其实就是这个块的信息了,这更加体现了一种分治的思想。

对于Super blocks,它的名字可就厉害了,叫做超级块,存放的是文件系统本身的结构信息,而且不是每个组都有的,可能几个组才回有一个。比如存放的有inode使用的个数,未使用的个数,datablocks的使用个数,datablocks未使用的个数。这些都是超级块所要记录的内容。

那么提问,既然是记录所有的结构信息,为什么要整这么多个呢?

因为磁盘是可能损坏的,如果损坏的时候,刚好磁头给一个超级块的内容消除了,那么这不就完蛋了吗??所有多存储几个,增加了容错率!!

说了那么多,inode是十分重要的,查看inode是-i:


细节理解

对于上文来说,我们已经理解了块里面的6个成员,现在我们来谈论具体细节问题:

第一个细节:

如何通过inode找到对应的data blocks?

因为inode和data都是以分区为单位的,所以inode可以通过数组datablocks找到的!

第二个细节:

我们使用的不是一直都是文件名吗?好像并没有使用inode,可是我们改变文件内容的时候,一直使用的都是文件名啊?

这个时候,我们就要谈谈目录了,目录 = 文件属性 + 文件内容,这里可不要认为目录就不是文件了,提问,目录的文件内容是什么呢?

目录的文件内容 = 文件名和inode的编号关系,当我们创建好了一个文件,文件所在的目录就会记录该文件和inode的关系,方便找到并进行修改。

所以目录里面的文件名就是和inode映射关系!!

到了这里,相信同学们能理解为什么一个目录下不能创建多个同名文件了吧?因为如果创建了同名文件,映射关系一乱,整个文件系统就瘫痪了。

可是!!当我们修改目录的时候,用的还是目录名啊!!又是什么存储的目录和inode的关系呢?

看这个:

pwd打印出来了路径,是因为环境变量PATH,而我们在该目录下修改文件,需要找到对应的inode,找到inode之前,我们需要找到该文件所在的目录,找到该文件所在的目录,我们就应该要找到目录的目录,最后直接到了根目录!!

而在根目录这里,就是OS已经提前加载好了有关路径缓存的信息了,这里涉及到了知识点有结构体dentry,格式化,挂载等。我们先不管,我们只需要知道,Linux会缓存路径信息,从而我们可以通过文件 目录来修改对应内容。

现在,我们顺便回顾一下目录的r w,当我们将r去掉之后,也就是没有可读权限:

此时目录就不允许我们读取文件内容,本质就是不让我们知道文件名和inode的映射关系。

这里就不演示了,当我们没有了w权限之后,我们无法创建文件,本质就是因为不要我们创建文件名和Inode的映射关系!!

所以,对于细节2,我们可以得出结论:

1 目录下不能创建同名文件,因为会打乱映射关系

2 查找的文件顺序是通过文件名查找对应的inode编号

3 r是让我们找到对应的映射关系,w是不让我们写入对应的映射关系

第三个细节:

我们如何理解文件的增删查改呢?

文件增,就是找到对应的映射关系,在datablock里面增加数据,查就是找对应的映射关系,改也是通过inode,修改datablocks里面的数据关系。

那么删除呢?

其实这里的删除是一种伪删除。

即将Inode bitmap , datablock bitmap都置为0即可。这是一种删除。

我们对于文件系统的框架有了简单的理解,那么理解接下来的软硬连接动态库就会轻松很多了。


感谢阅读!

标签: linux 运维 服务器

本文转载自: https://blog.csdn.net/2301_79697943/article/details/143166235
版权归原作者 _lazy. 所有, 如有侵权,请联系我们删除。

“初识Linux · 文件系统”的评论:

还没有评论