好奇是进步的第一步。
对于已经比较熟悉Linux命令行操作的朋友来说,下面这个命令一定不陌生:
ls -l
//有些时候可以简写为 ll
//ls 命令
//list files
//—— 命令用于显示指定工作目录下之内容
// 即,列出目前工作目录所含之文件及子目录。
//-l 参数
//除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
既然我们可以在Linux操作系统中通过命令查看到关于文件的如此多的信息,那么这些信息究竟是以何种方式,如何存储的?这便要提到文件系统了。
文件系统
我们都知道的是,文件是存储在硬盘上的。
硬盘上最小的存储单元被称为“扇区”,每个扇区的大小为512字节,但对于我们计算机的整个硬盘的大小来说,512字节实在是太小了,当操作系统从硬盘中读取信息时,如果一个扇区一个扇区地读,效率实在是太低了。
所以,操作系统在扇区的基础上,将数个扇区合并为一个文件存取的基本单元,称之为“块”,操作系统每次读取时,都是以块为单位进行的。
当然,“块”这个概念只是对于文件系统来说的,对磁盘来说是不存在“块”的概念的,磁盘只有“扇区”。
通常情况下,块的大小为4KB,也即8个扇区。这个值可以在格式化分区时修改。但通常情况下不建议修改,因为,当块过大时,虽然读取效率提高了,但更容易导致空间的浪费;如若块设置的过小了,又会导致读取效率的降低。对于初学者来说,我们并不具备根据业务合理调整“块”的大小的能力,贸然修改,可能得不偿失。
操作系统将文件数据以“块”为单位在磁盘中存取,同时操作系统还需要一个地方来存储文件的元信息,就如我们上方所看到的,文件的创建者,文件的权限,文件的日期以及文件的大小等等,操作系统所需存取的元信息远比 ls -l 命令所显示的详细的多。而用户可以通过:
stat [文件名]
来查看更加详细的文件元信息。如:
存储文件的元信息的区域被称为inode。
inode的本质是一个结构体,用来存储文件系统中各个文件相关的重要信息。而inode的具体之原理,则涉及到我们本篇的核心知识点——文件系统。在此我们以ext2文件系统为了解对象:
boot block:引导块,位于第0号扇区,它并不属于一般的文件系统管辖,为根文件系统所特有,在此不做介绍(因为我暂时也不咋清楚)
块组:为了方便对磁盘管理,文件系统将磁盘空间划分为若干组,以一组为单位来管理磁盘空间,这个组被称为“块组”。
超级块:它可以称得上是文件系统的心脏,如果超级块损毁了,我们几乎可以认定这块磁盘没救了。一个文件系统是由它的超级块来定义的。超级块中存放了文件系统本身的结构信息,其中包括了block与inode的总量,未使用的block与inode的总量等等。
块组描述符表(GDT):ext文件系统的对每一个块组都使用了32字节描述,这32个字节被称为块组描述符,所有的块组描述符在一起组成了块组描述符表,即GDT。它并不一定存在于每一个块组中,但它一定与超级块在一起……
块位图:Block Bitmap。块位图当中记录了哪个数据块已经被占用,哪个数据块还没有被占用。
inode位图:每个bit位表示着一个inode节点是否空闲。
i节点表:inode的本质是结构体,存储着与文件有关的所有元信息。而inode表是由inode结构体组成的,每个项目都是一个inode,可以通过inode号码来调用。
数据区:存放文件内容。
关于文件系统中的inode结构体,其内保存的文件元信息具体来说有以下内容:
1.文件的大小(字节数)
2.文件的拥有者id
3.文件所属的组的id(Group id)
4.文件的模式(包括文件类型与文件权限)
5.文件的时间戳,分别为:
最近访问(Access):文件上一次打开时间
最近更改(Modify):文件内容上一次变动时间
最近改动(Change):inode上一次变动时间
6.链接数:有多少文件名指向这个inode
7.文件数据所存储的块(block)位置
8.这个inode的编号
讲到文件系统,不可避免的要讲一下创建文件时内核的操作了,大体来说分为以下四个操作:
1.存储属性
内核通过inode位图找到一个空闲的inode,内核将文件信息记录其中。
2.存储数据
内核根据文件大小得知该文件需要多少个磁盘块,然后依次将内核缓冲区的数据块拷贝到磁盘块中。
3.记录分配情况
文件内容再磁盘中按顺序存放,内核在inode结构体中磁盘分布区按同样顺序记录块列表。
4.添加文件名到目录
内核将inode节点号与文件名放入目录文件,文件名与inode之间的对应关系将文件名和文件的内容及属性连接起来。
如上方所提到的,我们所熟知的文件夹,也叫做目录(directory),在Linux操作系统中也是一种文件。打开目录,实际上就是打开目录文件。
不过目录文件的结构非常简单。它是一系列目录项组成的列表。
每个目录项由两部分组成,即所包含文件的文件名,以及该文件名对应的inode号码。
我们可以通过以下命令来查看整个目录文件:
ls -i [目录文件]
软硬链接的再次理解
如图,图中的 fd 与 fp 之间以及 1.txt 与 3.txt 是软链接关系,而 2.txt 与 4.txt 之间是硬链接关系。
在Unix/Linux操作系统中,允许多个文件指向同一个inode号码。
硬链接的本质就是不同的文件名指向了相同的inode号码。
这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。
而软链接则复杂一点
源文件与链接文件的inode号码不同,但链接文件中的内容是源文件的路径。在读取链接文件时,系统会自动将访问者导向源文件。
所以无论打开哪一个文件,最终读取的都是源文件。
ln -s [源文件] [目标文件(链接文件)]