Linux文件系统概述

1.1 简介

文件系统是解决如何在存储设备上存储数据的一套方法,包括存储布局、文件命名、空间管理、安全控制等。Linux操作系统支持很多现代的流行文件系统,其中ext2、ext3和ReiserFS最普遍。ext2文件系统是伴随着linux一起发展起来的,在ex2的基础上增加日志就是ext3,这两个文件系统可以很容易的转换而不必重新格式化存储介质,它们是linux特有的。ReiserFS可以说是后起之秀了,最初它不是用于linux,所以对linux来说它是一个泊来品。ReiserFS采用了一个非常先进的新颖算法,最新的4版本真正做到了文件系统操作的原子性(类似数据库事务操作的原子性),据官方报道,ReiserFS“原子性”算法优于现代数据库的“原子性”算法,做到了空间和时间复杂度的双优!一个文件系统能做到这个份上,我算是彻底服了🙂

现代Linux系统继续采用了早期(1992年前)发展的虚拟文件系统(Virtual File System,简写为VFS)理念,VFS是一个介于用户和实际文件系统之间,为用户提供了一个统一的编程接口,尽管处于其之下的各种文件系统类型千差万别,但对最终用户来说却是一样的。例如当用户张三输入命令cd /data后,他并没有意识到自己刚从ext3文件系统进入ReiserFS文件系统,他仍然使用命令ls –l列出当前目录下的所有文件,而且显示格式也是一样,但是幕后英雄VFS可忙坏了,它不得不启动一个算法找到ReiserFS文件系统提供的接口函数并调用它们,要知道ReiserFS提供的一套函数可不同于ext3的那一套。得益于VFS,其他文件系统可以采用“热插拔”的非常简便的方式加入或退出Linux操作系统,例如当第一次mount一个文件系统A时,相应地就把该文件系统对应的模块装载到内核(假设没有被直接编译进内核),当最后把文件系统A对应的设备umount时,对应的模块被卸载出去。

1.2 原理

LINUX的文件系统可以追溯到八十年代末的Minix文件系统,而Minix文件系统具有几个明显的缺点:文件系统不能超过64M,目录只能存放固定数目的文件,文件名长度不能超过14个字符,文件尺寸小于64M。之后由于继续沿袭传统技术,尽管linux的标准文件系统依次经历了VFS(1992年前)、ext(1992年)、ext2(1993年)和最新的ext3这一系列文件系统的传种接代,但“基因”没变,只不过新一代都是改进前一代的不足,或者加入一些新东东而已。但由于Linux几乎在一开始就引入VFS的概念(我个人认为非常英明^O^),Linux对其他第三方文件系统都是包容的,目前几乎所有先进的文件系统都支持,其中著名的ReiserFS已经成了Novell的SuSe Linux发行版的缺省文件系统,但也由于IT界最臭名昭著的四字经“向后兼容”的要求,今日各种linux发行版中存在过多地包容早已经落伍的文件系统的现象,比如Minix、FAT等,但对于一个富有理论和经验的系统管理员来说,所有的这些“累赘”都可以在弹指间一一化解。

下面我们先看看一块物理硬盘是如何分区的。三个主要的参数是柱面数、磁头数和每磁道扇区数,起始编号分别为0、0和1,0柱面0磁头1扇区是主引导分区,上面存放引导代码和四个主分区表(如果一个物理硬盘多于4个,那么就放在扩展分区),0柱面0磁头上的其他扇区保留,真正的分区是从0柱面1磁头1扇区开始的。在linux中,用/dev/had、/dev/hdb、/dev/sda、/dev/sdc等表示一个物理磁盘。实验:

1).       查看硬盘物理参数:hdparm /dev/sda; hdparm –i /dev/had(IDE硬盘);

2).       读入分区表信息:dd if=/dev/sda of=/tmp/mbr bs=1 count=64 skip=446;

3).       查看主分区表信息:od –t x1 mar;

4).       备份主引导区信息:dd of=/dev/sda if=/dev/sda bs=512 count=1 seek=1;

 

1.2.1 VFS

自从VFS投胎于linux以来(Mr. Linus不愧为一个有远见的接生婆,@_@),VFS就一直与Linux形影不离,并且成了Kernel的一部分,在Kernel版本号如芝麻开花般节节攀升的同时自己也枝繁叶茂起来。

VFS就像一个一个默默无闻的公仆,它介于各种文件系统和用户进程之间(参见图1.1),一方面屏蔽下层的各种异构文件系统的个性,另一方面为上层用户提供一个统一的接口(如open、read等),同时VFS还提供一些文件系统没有的操作,比如,没有哪个文件系统提供了函数lseek,此函数由VFS实现。

Kernel中存在一个全局指针变量file_systems,该变量指向一个元素类型为file_system_type的链表,当mount一个文件系统时装载对应的模块,而装载模块时触发的行为register_filesystem()会生成一个file_system_type结构并把它挂接到file_systems链表上,也就是说所有的已经mount的文件系统都挂在这个链表上,file_system_tpe结构中有一个指向超级块结构的指针,存储介质上的超级块在设备mount时被读入内存,直到umount时从内存中删除。

vfs

图1.1 VFS在内核中的位置

1.2.2EXT2和EXT3

EXT2是linux上标准的文件系统,EXT3是在EXT2基础上增加日志形成的,其思想还是可以追溯到早期UNIX家族发展的基于超级块和inode的经典概念。/dev/sda#n表示/dev/sda硬盘上的第#n个分区,如果一个分区备格式化为ext2或ext3文件系统,那么整个分区的布局如图1.2所示:

ext2_disk

图1.2:EXT2文件系统分区结构

分区上的扇区是从0开始编号的,每个扇区512bytes,一个块(block)大小一般是1k、2k、3k和4k,具体大小可在创建文件系统时指定,如果不指定块大小那么会根据分区的大小自动相应选择一个。分区开始的1024bytes存放引导程序boot,接下来的1024bytes存放超级块super block,组描述字group descriptors起始于一个新块,并单独占用一个块空间,之后的所有块被组织成块组,块组才是真正存放文件的场所。超级块含有整个文件系统的一些全局参数,如:卷名、全局唯一标识符、状态、块大小、总块数、每组inode数,总i节点数、每组块数等等,super block在文件mount时被读入内存,直到umount时被释放,由于超级块对于文件系统来说至关重要,所以超级块一般在第1、3、5、7和9组的首块中存有副本。

实验:

1).创建一个ext2文件系统:mke2fs –c –c –L “Test Filesystem” /dev/sda2;

2).查看ext2分区开始部分的信息:od –t x1 /dev/sda2 | more;其中“aa55”之前的为boot,含有魔数“ef53”的区域为super block;

3).查看超级块中的内容:tune2fs –l /dev/sda2;例子见附件1。

4).查看详细的块组信息:dumpe2fs –x /dev/sda2;例子见附件2。

一个块组描述字占用32个字节,其中三个主要指针分别指到到这个块组的i节点表、i节点位图和块位图。块组的设计是为了拉近inode和它的数据块的距离,这样就可以提高磁盘存取性能,一个块组的具体结构示意图见图〖二〗右边部分。

inode是EXT2文件系统的精华,一个inode对应一个文件,inode编号是全局性的,从1开始,描述参考图1.3。

ext2_inode

inode中存放文件的一些重要属性,如权限、文件大小、访问时间、修改时间、创建时间、文件属主ID、组ID、块数等。Inode包含15个指针,前12个直接指向数据块,后三个依次是一次间接、二次间接和三次间接指向数据块。

文件系统的目录不同于普通文件的结构,是一种固定格式的文件,里面的每一个条目代表目录中的一个文件,示意图见图1.4。

ext2_dir_it

图1.4 目录条目示意图

在ext2文件系统上增加一个特殊的inode(日志文件),用于记录文件系统元数据的变化,即日志journal,这就是EXT3文件系统。Ext3这种粗糙的实现日志的文法付出了很大的代价:写两次!

实验:ext2和ext3文件系统之间的转换(不需要重新格式化)

1).       ext2转换成ext3文件系统:tune2fs –j /dev/sda2;如果sda之前已经mount,那么该命令执行完后在顶层目录创建了一个不能删除和dump的日志文件.journal,机器重启或umount且e2fsck后该文件将被改变成隐藏的特殊日志文件inode。如果/dev/sda2是启动时自动mount的,那么还需手工修改/etc/fstab中/dev/sda2所对应的文件系统类型,否则还是按ext2类型mount和使用。

2).       ext3转换成ext2文件系统:umount /dev/sda2; tune2fs –O ^has_journal /dev/sda2; e2fsck –y /dev/sda2; mount –t ext2 /dev/sda2 /mnt; 对于自动mount的设备还需修改/etc/fstab。

如果引用本站的原创文章,请注明原文链接:,本站保留追究责任的权利!

发表评论