这两天在看《linux c 编程实战》的文件操作,学会了一些函数如open,read,lseek,stat等,但是学姐教导我们:要从宏观上把握知识,从根本上了解问题。所以,我就在这里浅显的谈一谈我最近学习的———文件系统。
0.什么是文件系统?
文件系统是一种存储和组织计算机数据的方法,它使得对其访问和查找变得容易,文件系统使用文件和树形目录的抽象逻辑概念 代替了硬盘和光盘等物理设备是使用数据块的概念,用户使用文件系统来保存数据不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个文件的所属目录和文件名。在写入新数据之前,用户不必关心硬盘上的那个块地址没有被使用,硬盘上的存储空间管理(分配和释放)功能由文件系统自动完成,用户只需要记住数据被写入到了哪个文件即可。
1.磁盘分区与目录
所有磁盘分区都必须被挂载到目录上才能使用。所谓的"挂载"就是利用一个目录当成进入点,将磁盘分区的数据放置在该目录下;也就是说,进入该目录就可以读取该分区的意思。这个操作我们称为"挂载",那个进入点的目录我们称为"挂载点"。由于整个Linux系统最重要的是根目录,因此根目录一定需要挂载到某个分区的。至于其他的目录则可依用户自己的需求来给予挂载到不同的分区。
上图中,假设我的硬盘分为三个区,分区1被挂载到根目录,分区2被挂载到/home这个目录,分区3被同时挂载在/var和/tmp目录上,也就是说,通过/home,我们可以访问到分区2的数据。同理,分区3的数据,我们可以通过/var和/tmp访
问到。而分区1里的数据,我们则可以通过/及其以下的目录访问到。所以,所有磁盘分区都必须被挂载后才可以使用,否
则系统会不知道这个分区的存在。每个分区可以包含一个文件系统。一个分区只有建立了文件系统(即分区的格式化)后,才可以使用。
2.文件系统的结构
我们看到的JFFS2,YAFFS,Ramfs,就是文件系统了。那么VFS又是什么?
VFS(Virtual File System “虚拟文件系统”)使得Linux可以支持多个不同的文件系统。VFS提供一种机制,它将各种不同的文件系统整合在一起,并提供统一的应用程序编程接口(API--是一些预先定义的函数)供上层的应用程序使用。也就是说,它是一个可以让open()、read()、write()、mkdir()等系统调用不用关心底层的存储介质和文件系统类型就可以工作的粘合层。
3.文件系统内各部分的功能
*在文件系统的整体规划中,文件系统最前面有一个自举块,这个自举块可以安装引导装载程序。
*超级块(superblock)是记录整个文件系统相关的信息的地方,它记录的信息主要有:block与inode的总量、使用
量、剩余量,文件系统的挂载时间,最近一次写入数据的时间等。可以说,没有超级块,就没有这个文件系统了。
*inode是用来记录文件属性的,比如说:文件的权限、所有者与组、文件的大小、修改时间等。一个文件占用一个
inode,系统读取文件的时候,需要先找到inode,并分析inode所记录的权限与用户是否符合,若符合才能够开始实际
读取block的内容。
*数据块(data block)是用来放置文件内容的地方,每个block内最多只能放置一个文件的数据。如果文件大于
block的大小,则一个文件会占用多个block数量。但如果文件小于block,则该block的剩余空间就不能够再被使用
了。
文件系统在一开始就将inode与block规划好了,但是如果我的文件系统高达数百G,那么数量如此之多的inode与block
会很难管理,因此Ext2文件系统在格式化的时候基本上是区分为多个块组(block group)的,每个块组都有独立的
inode/block/superblock系统。如下图所示
从上图我们可以看到,每个block group都可能含有superblock,但我们前面讲到一个文件系统应该仅有一个
superblock而已。事实上,除了第一个block group内会含有superblock之外,后面的block group不一定会
含有superblock,如果含有superblock,则该superblock主要是作为第一个block group内superblock的备份
了。这样可以进行superblock的救援。
我们知道,每个inode与block都有编号,因此,如果能找到文件的inode,那么就可以知道这个文件放置数据的block号
码,自然也就可以读出该文件的实际数据了。我们来图解说明一下
假设某文件的属性与权限等数据是放置在inode4号,这个inode记录了文件文件数据的实际放置点为2、7、13、15
这4个block号码,此时我们的操作系统就能够据此来排列磁盘的阅读顺序,可以一下子将4个block的内容读出来。
这种数据访问的方法我们称为索引式文件系统。作为对比,我们来看看U盘所使用的FAT文件系统的数据访问方式。
上图中假设文件数据依次被写入1—>7—>4—>15号这四个block号码中,但这个文件系统没有办法一次性就知道4个
block号码,它得要一个一个地将block读出后,才会知道下一个block在哪儿,如果一个文件数据写入block分散的太厉
害时,那么磁盘需要多转好几圈才能完整的读取到这个文件的内容。
4.文件系统的运行
说了这么多,文件究竟是怎么被读取的,举例来说,如果我想要读取/dev/bus这个文件时(假设读取者身份为sry这个一般用户):
1./的inode
通过挂载点的信息找到inode号码为2的根目录inode,且inode具有的权限(r与w)允许我们读取该block的内容。
2./的block
经过步骤1取得的block号码,并找到该内容有dev/目录的inode号码(1025)。
3.dev的inode
读取1025号inode得知sry具有r与x的权限,因此可以读取dev/的block内容。
4.dev/的block
经过上个步骤取得block号码,并找到该内容有bus文件的inode号码(1177)。
5.bus的inode
读取1177号inode得知sry具有r与w的权限,因此可以读取bus的block内容。
6.bus的block
最后就可以将该block内容的数据读取出来了。