ext2文件系统
- 格式:docx
- 大小:402.05 KB
- 文档页数:21
简述linux文件系统的类型Linux文件系统的类型文件系统是操作系统中用来组织和管理文件的一种机制。
Linux作为一种开源的操作系统,拥有多种不同的文件系统类型来适应不同的需求和场景。
本文将对常见的Linux文件系统类型进行简要介绍。
1. ext4文件系统ext4(Fourth Extended File System)是Linux中最常用的文件系统类型之一。
它是对ext3文件系统的改进和升级,具有更好的性能和稳定性。
ext4文件系统支持最大16TB的单个文件,最大1EB的文件系统大小,同时支持日志功能,可以在系统崩溃后快速恢复文件系统。
2. ext3文件系统ext3(Third Extended File System)是ext2文件系统的改进版本,它添加了日志功能以提供更好的数据一致性和可靠性。
相比ext2,ext3具有更好的容错能力,可以在系统崩溃后更快地恢复文件系统。
ext3文件系统最大支持16TB的文件大小和8TB的文件系统大小。
3. ext2文件系统ext2(Second Extended File System)是Linux中最早的一种文件系统类型,它为Linux提供了一个可靠的文件存储机制。
ext2文件系统采用了索引节点(inode)的结构来组织文件和目录,支持文件和目录的权限和属性设置。
然而,ext2文件系统没有日志功能,对于系统崩溃或断电等异常情况,恢复文件系统需要较长的时间。
4. XFS文件系统XFS是一个高性能的日志文件系统,最初由SGI开发,后来被红帽公司广泛采用。
XFS文件系统支持最大8EB的文件系统大小和最大8EB的单个文件大小。
它具有快速的文件系统检查和修复功能,并且能够高效地处理大文件和大量小文件。
5. Btrfs文件系统Btrfs(B-tree file system)是一个基于B树的文件系统,它是Linux内核的一部分,并且正在逐渐取代ext4成为Linux中的主流文件系统。
标题:深入探讨ext2文件的逻辑结构和物理结构的映射过程在计算机科学领域,文件系统是操作系统中的重要组成部分,用于管理文件的存储和检索。
而ext2文件系统是Linux操作系统中常见的文件系统之一,其结构复杂、功能强大。
在本文中,我将深入探讨ext2文件系统的逻辑结构和物理结构的映射过程,以便更好地理解这一主题。
一、理解ext2文件系统1. ext2文件系统的基本概念在开始深入讨论ext2文件系统的逻辑结构和物理结构的映射之前,需要首先理解ext2文件系统的基本概念。
ext2是Linux操作系统中常见的文件系统类型,它采用了类Unix文件系统的基本概念,包括inode、超级块、块组描述符等重要概念。
2. ext2文件系统的特点ext2文件系统具有一些独特的特点,如支持大容量的文件系统、高效地组织和管理磁盘空间、高速的文件读写性能等。
这些特点使得ext2文件系统在Linux系统中得到了广泛的应用。
二、逻辑结构和物理结构的映射过程1. 磁盘空间的组织ext2文件系统的逻辑结构和物理结构的映射过程首先涉及到磁盘空间的组织。
磁盘空间被组织成多个块组,每个块组包含若干个数据块,用于存储文件数据;同时还包含若干个inode块,用于存储文件的元数据信息。
2. inode与文件的映射在ext2文件系统中,每个文件都对应一个唯一的inode,该inode记录了文件的元数据信息,如文件大小、权限、所有者等。
逻辑上,文件可以通过inode进行标识和管理,而物理上,inode则映射到具体的磁盘块中。
3. 数据块的映射文件的实际数据则存储在数据块中。
数据块的映射过程是ext2文件系统逻辑结构和物理结构的重要部分,它涉及到磁盘空间的分配和管理,以及文件数据与磁盘块的对应关系。
三、个人观点和总结通过对ext2文件系统的逻辑结构和物理结构的映射过程进行深入探讨,我对文件系统的工作原理有了更深入的理解。
在实际应用中,对文件系统的深入理解能够帮助我们更好地进行文件管理和存储空间的优化,提高系统的性能和稳定性。
常用的linux文件系统类型Linux操作系统是一种开源的操作系统,它的文件系统类型非常丰富。
不同的文件系统类型可以支持不同的文件大小、文件数量和文件系统的速度等特性。
本文将对常用的Linux文件系统类型进行介绍,以帮助读者选择最适合自己需求的文件系统类型。
1. ext2ext2是Linux最早的文件系统类型之一。
它被广泛使用,因为它很稳定,而且在Linux内核中得到了很好的支持。
它支持最大2TB 的文件系统,并且允许使用文件名长达255个字符。
但它不支持文件的访问控制,因此在安全性方面不太可靠。
另外,由于它没有日志功能,因此在文件系统崩溃后需要进行长时间的文件系统检查。
2. ext3ext3是ext2的升级版本,它添加了日志功能。
这意味着在文件系统崩溃后,ext3可以更快地恢复,而且文件系统的可靠性也更高。
它还支持最大16TB的文件系统,并且可以使用文件名长达255个字符。
但它的速度较慢,因为每次写入都需要写入日志。
3. ext4ext4是ext3的升级版本,它支持最大1EB的文件系统,而且可以使用文件名长达255个字符。
它的速度比ext3更快,因为它使用了更先进的数据结构,同时它的文件系统检查速度也更快。
此外,它还支持更高级的文件访问控制,因此在安全性方面更可靠。
4. XFSXFS是一种高性能的文件系统类型,它可以支持非常大的文件和文件系统。
它支持最大9EB的文件系统,并且可以使用文件名长达255个字符。
它的速度非常快,因为它使用了先进的算法和数据结构。
但它的可靠性不如ext4,因为它在文件系统崩溃后需要进行长时间的文件系统检查。
5. BtrfsBtrfs是一种新型的文件系统类型,它被设计用于支持大型文件系统和高级数据管理功能。
它支持最大16EB的文件系统,并且可以使用文件名长达255个字符。
它支持数据快照、压缩、复制和校验等高级功能。
但它还不够稳定,因为它还没有被广泛使用。
6. NTFSNTFS是Windows操作系统使用的文件系统类型,但它也可以在Linux上使用。
ext2⽂件系统学习(⼆)——⽬录磁盘结构创建镜像、mount等操作和上⼀篇⼀样,测试⽬录结构如下:⼀些⽂件系统信息如下:Block size: 1024Inodes per group: 128Inode size: 128Block bitmap at 6Inode bitmap at 7Inode table at 8-23下⾯看看⽂件系统根⽬录的结构,ext2的根⽬录的索引节点号是2,根据上⾯的信息可以计算出根⽬录的索引节点地址是0x002080。
如果是⽤vim打开的镜像⽂件,可以通过以下命令计算地址::echo printf("%x", 8*1024+128)⽂件内容如下:对照结构定义:i_mode: 0x41ed 对照可知⽂件格式为EXT2_S_IFDIRi_uid: 0i_size: 0x000400,也就是1K (可以通过ls -ld /tmp/ext2验证)i_block: 0x000018,说明该⽬录只占⽤了⼀个block,地址为0x18 * 1024=0x6000,这⾥也就是根⽬录的内容0x6000地址处内容如下:ext2的⽬录是⼀个特殊的⽂件,⽂件内容是多个结构的⽬录项,每个⽬录项是⽂件名和索引节点的集合。
对照ext2_dir_entry_2的结构,第⼀个⽬录项信息如下:inode : 2rec_len: 0x000Cname_len: 0x01file_type: 0x02,表⽰⽬录name: 0x2E,也就是“."因为上⼀个⽬录项rec_len是0x0C,所以下⼀个⽬录项地址为0x600C,对应⽬录项信息如下:inode: 2rec_len: 0x000Cname_len: 0x02file_type: 0x02,表⽰⽬录name: 0x2E,0x2E,也就是“..”下⼀个⽬录项地址为上⼀个⽬录项地址加上上⼀个⽬录项的rec_len,也就是0x600C + 0x0C = 0x6018,信息如下:inode: 0x0B,11rec_len: 0x14,20name_len: 0x0A,10file_type: 0x02, 2,表⽰⽬录name: 0x6C,0x6F, ...,也就是“lost+found”以此类推就可以找到所有根⽬录下的⽬录项。
EXT2、EXT3、EXT4、XFS、GPT详解原创:运维老司机小柒博客7月18日EXT2与EXT3区别Linux之前缺省情况下使用的文件系统为Ext2,ext2文件系统的确高效稳定。
但是,随着Linux系统在关键业务中的应用,Linux文件系统的弱点也渐渐显露出来了:其中系统缺省使用的ext2文件系统是非日志文件系统。
这在关键行业的应用是一个致命的弱点,Ext3文件系统是直接从Ext2文件系统发展而来,目前ext3文件系统已经非常稳定可靠。
它完全兼容ext2文件系统。
用户可以平滑地过渡到一个日志功能健全的文件系统中来。
这实际上了也是ext3日志文件系统初始设计的初衷。
1) ext3和ext2的主要区别在于,ext3引入Journal(日志)机制,Linux内核从2.4.15开始支持ext3,它是从文件系统过渡到日志式文件系统最为简单的一种选择,ext3提供了数据完整性和可用性保证。
2) ext2和ext3的格式完全相同,只是在ext3硬盘最后面有一部分空间用来存放Journal的记录;3) 在ext2中,写文件到硬盘中时,先将文件写入缓存中,当缓存写满时才会写入硬盘中;4) 在ext3中,写文件到硬盘中时,先将文件写入缓存中,待缓存写满时系统先通知Journal,再将文件写入硬盘,完成后再通知Journal,资料已完成写入工作;5) 在ext3中,也就是有Journal机制里,系统开机时检查Journal的内容,来查看是否有错误产生,这样就加快了开机速度;EXT3日志文件系统的特点1、高可用性系统使用了ext3文件系统后,即使在非正常关机后,系统也不需要检查文件系统。
宕机发生后,恢复ext3文件系统的时间只要数十秒钟。
2、数据的完整性ext3文件系统能够极大地提高文件系统的完整性,避免了意外宕机对文件系统的破坏。
在保证数据完整性方面,ext3文件系统有2种模式可供选择。
其中之一就是"同时保持文件系统及数据的一致性"模式。
Linux ext2ext2文件系统是早期Linux发布版的基础,Linux默认直接支持的文件系统。
该文件系统非常优势,也是ext3文件系统的基础。
ext2文件系统和其他现代Unix 使用的文件系统非常相似,但更接近于BSD(Berkeley Software Distribution:Berkeley 软件分发版)系统所用的Berkeley Fast Filesystem。
ext2文件系统除了具有标准功能外,还支持一般Unix文件系统中所没有的高级功能,如设置文件属性、支持数据更新时同步写入、允许磁盘管理员在创建文件系统时选择逻辑数据块的大小、实现快速符号链接以及提供两种定期强迫进行文件系统工具等。
1.ext2文件系统的物理结构ext2文件系统像多数文件系统一样,建立在文件数据存放在数据中的前提下。
ext2文件系统中的数据块具有相同的长度,虽然不同的ext2文件系统的块长度可以不同,但是对于某个特定的ext2文件系统,它的块长度在创建的时候就已经确定了。
每一个文件的长度都会按照块取整,例如,存在一个文件1025字节,而一个块的大小为1024字节时,该文件就会占用两个1024字节的块,这就意味着平均每一个文件都有可能浪费一部分磁盘空间。
每个块包含了相同的信息如:超级块、块组描述结构、块位图索引节点、索引点表和数据块等内容,图4-2演示了ext2文件系统的物理结构。
图4-2 ext2物理结构2.块组的构造从图4-2中可看到每一个块组都重复保存着一些有关整个文件系统的关键信息,以及真正的文件和目录的数据块。
超级块包含有文件系统本身的大小和形式的基本信息,系统管理员可以利用这些信息使用和维护文件系统。
在安装文件系统时,系统只读取数据块组1中的超级块,将其放入内存直到该文件系统被卸载,超级块中包含了以下内容。
●块数用于确认安装的文件系统是否为ext2的超级块。
●修订级别这是文件系统的主版本号和次版本号。
ext2读取文件原理以ext2读取文件原理为题,本文将介绍ext2文件系统是如何读取文件的。
ext2是一种常用的Linux文件系统,被广泛应用于Linux 操作系统中。
我们需要了解一下ext2文件系统的基本结构。
ext2文件系统将存储设备划分为多个块组,每个块组都包含了若干个数据块和一些元数据。
元数据包括了超级块、块位图、inode位图和inode表等。
超级块记录了整个文件系统的重要信息,如块大小、块组大小、inode数量等。
块位图用于记录数据块的使用情况,而inode位图则用于记录inode的使用情况。
inode表中存储了每个文件的元数据信息,如文件类型、权限、大小、访问时间等。
每个文件和目录都对应一个inode。
当我们要读取一个文件时,首先需要找到该文件所在的inode。
我们可以通过目录来查找文件的inode。
每个目录都包含了一系列的目录项,每个目录项都对应一个文件或子目录。
目录项中记录了文件名和对应的inode号,通过遍历目录项,我们可以找到目标文件的inode。
找到目标文件的inode之后,我们就可以通过inode中的数据块指针来读取文件的内容。
ext2文件系统中的文件数据块被组织成一棵多级索引的树状结构。
inode中的数据块指针包括了直接块指针、一级间接块指针、二级间接块指针和三级间接块指针。
直接块指针直接指向文件的数据块,而间接块指针则指向一级、二级或三级块。
通过多级间接块指针的组合,我们可以寻址到任意数据块。
在读取文件时,我们首先通过直接块指针读取文件的直接数据块。
如果文件的大小超过了直接块的容量,那么我们需要通过一级间接块指针来读取更多的数据块。
一级间接块中存储了多个二级块的地址,通过二级间接块指针,我们可以读取更多的数据块。
同样地,如果文件的大小超过了一级间接块的容量,我们就需要通过二级间接块指针来读取更多的数据块。
二级间接块中存储了多个三级块的地址,通过三级间接块指针,我们可以再次读取更多的数据块。
简述linux操作系统中的文件系统类型及其区分方法Linux 操作系统支持多种文件系统类型,这些文件系统类型可以通过文件系统驱动程序来挂载。
常见的文件系统类型包括 ext2、ext3、ext4、xfs、swap 等。
下面对这些文件系统类型进行简要介绍:1. ext2/ext3/ext4:这是Linux中最常用的文件系统类型之一,支持文件压缩、日志记录等功能。
其中,ext2/ext3是早期版本的文件系统,而ext4则是ext3的升级版,支持更大的文件和更好的性能。
2. xfs:这是一种支持无损数据压缩和扩展文件系统大小的文件系统。
xfs 文件系统在 Linux 中常用于高端服务器和工作站上。
3. swap:这是一种虚拟内存文件系统,用于在系统内存不足时充当磁盘缓存。
swap 文件系统可以将磁盘空间用作内存缓存,提高系统性能。
4. 其他文件系统类型:除了以上常见的文件系统类型,Linux 还支持其他文件系统类型,如 reiserfs、jffs2 等。
reiserfs 是一种优秀的文件系统类型,支持文件压缩和索引功能,而 jffs2 则是一种基于 JFFS 文件系统类型的深度压缩文件系统。
要区分这些文件系统类型,可以通过命令行或者文件系统检测工具来实现。
例如,在 Linux 中,可以使用 fsck 命令来检查文件系统类型,也可以使用mount 命令来挂载文件系统。
此外,一些文件系统检测工具,如 parted、gdisk 等,也可以用于检测和转换文件系统类型。
Linux 系统自身可以通过文件名、文件属性等信息来识别文件系统类型。
例如,在 Linux 中,文件系统类型可以通过文件名中的“-”或者“.”等符号来表示。
例如,一个文件名为“/dev/sda1”的文件系统类型为 block 设备文件,而一个文件名为“/home/user/ Documents”的文件系统类型为符号链接文件。
此外,Linux 系统还可以通过文件系统驱动程序来挂载文件系统,从而识别文件系统类型。
前述:Linux系统管理员很重要的任务之一就是管理好自己的磁盘文件系统,每个分区不可太大也不可以太小,太大会导致磁盘容量的浪费,太小会导致产生的文件无法存储的问题。
在Linux里面文件是由两部分数据组成,一部分是metadata,另一部分是data。
那么这些数据都存放在文件系统的什么地方呢?这就让我们必须得了解文件系统的Inode与Block 的基本原理了,而Linux最传统的磁盘文件系统使用的是Ext2,所以我们了解下它的内部原理。
第一部分:磁盘的组成和分区(基础)磁盘的机械部分:1、圆形的盘片(主要记录数据的部分)2、机械手臂与机械手臂上的磁头(可读写盘片上的数据)3、主轴马达,可以转动盘片,让机械手臂的磁头在盘片上读写数据磁盘的基本概念1、扇区是最小的物理存储单元(512bytes)2、将扇区组成一个园,那就是柱面,柱面是分区的最小单位3、第一个扇区最重要,里面有硬盘的主引导程序(MBR)占446bytes和分区表(partision tables)占64bytes。
4、目前流行的家用硬盘接口SATA和服务器硬盘接口SAS。
磁盘分区部分:1、主分区和扩展分区最多可以有4个(硬盘的限制)2、扩展分区最多只能有一个(操作系统限制)3、逻辑分区是由扩展分区分化出来的分区4、主分区和逻辑分区的内容可以被格式化,而扩展分区无法格式化第二部分:文件系统的基本特性我们都知道硬盘分区后都是需要格式化,之后操作系统才能使用该分区,为什么呢?这是因为各种操作系统的文件的属性和权限并不相同的,为了能够存放这些文件,因此将分区格式化,以成为操作系统能利用的系统格式。
文件系统通常会将两部分的数据分别放在不同的块,权限与属性放置到inode中,实际的数据放置到data block块中,另外还有一个超级块(superblock)会记录整个文件系统的整体信息,包括inode和block的总量、使用量、剩余量,以及文件系统的格式与信息。
本文主要讲述Linux 上比较流行的ext2 文件系统在硬盘分区上的详细布局情况。
Ext2 文件系统加上日志支持的下一个版本是ext3 文件系统,它和ext2 文件系统在硬盘布局上是一样的,其差别仅仅是ext3 文件系统在硬盘上多出了一个特殊的inode(可以理解为一个特殊文件),用来记录文件系统的日志,也即所谓的journal。
由于本文并不讨论日志文件,所以本文的内容对于ext2 和ext3 都是适用的。
1 前言本文的资料来源是Linux 内核中ext3 文件系统的源代码。
为了便于读者查阅源代码,本文中一些关键的技术词汇都使用了内核源代码中所使用的英语单词,而没有使用相应的中文翻译。
(这种方法是否恰当,还请读者朋友们指教。
)2 粗略的描述对于ext2 文件系统来说,硬盘分区首先被划分为一个个的block,一个ext2 文件系统上的每个block 都是一样大小的,但是对于不同的ext2 文件系统,block 的大小可以有区别。
典型的block 大小是1024 bytes 或者4096 bytes。
这个大小在创建ext2 文件系统的时候被决定,它可以由系统管理员指定,也可以由文件系统的创建程序根据硬盘分区的大小,自动选择一个较合理的值。
这些blocks 被聚在一起分成几个大的block group。
每个block group 中有多少个block 是固定的。
每个block group 都相对应一个group descriptor,这些group descriptor 被聚在一起放在硬盘分区的开头部分,跟在super block 的后面。
所谓super block,我们下面还要讲到。
在这个descriptor 当中有几个重要的block 指针。
我们这里所说的block 指针,就是指硬盘分区上的block 号数,比如,指针的值为0,我们就说它是指向硬盘分区上的block 0;指针的值为1023,我们就说它是指向硬盘分区上的block 1023。
MINIX, EXT2,FAT文件系统概要分析关键词:MINIX EXT2FAT FAT32分析Title: 概述了MINIX,EXT2,FAT文件系统,看完应该有一个全局的了解Author: QuanDate: 18.04.2006====================MINIX:====================Minix的文件系统主要包括一下6个部分:引导块,超级块,i节点位图,区段位图,真正的i节点信息,数据。
引导块:一般来将,每一个文件分区里面,都必须包含一个引导块。
虽然并不是每一个设备的分区都是用来引导的,但是,出于结构的统一以及兼容性方面的考虑,一般文件系统需要将分区的第一个块保留为引导块。
因此,我以前曾经犯过的一个错误就是,认为启动盘在windows里面是不能够被识别的,会提示磁盘未格式化。
看来我真的是错了,只能将那个启动盘上的系统,windows不能够识别。
但是,启动盘里面确实也装载着完整的文件系统。
超级块:之所以称之为超级块,就是因为这个块是整个文件系统的龙头!从它,可以推算出整个文件系统的信息。
在minix中,它包含了i节点数,区段数,块/区段比,最大文件长度,magic number等等信息。
这样,整个文件系统中,上面所涉及到的6个部分的分布就清楚了。
位图:常用的一个数据结构。
使用一个bit来代表一个有序逻辑单位,如这里的一个i节点,一个区段,或者是内存中的一页等等。
这里,使用位图来表示哪些i节点是可以的或者是不可用的,对于区段的使用方式也是相同的。
这样,就是对有序的逻辑单位进行了标记,而且这样的标记是写入磁盘的因此可以长期的保存。
所以,必须要确保文件系统的一致性(consistency),因为标记和真正的逻辑单位并不是同时写入磁盘的。
这一点,相当的重要。
i节点:这个结构和UNIX下的文件系统应该说是一样的。
这里保存着对应于每个文件的具体的信息,如文件类型,访问权限,链接信息,文件大小,时间信息,区段号(包括一次间接块和二次间接块)等等与文件密切相关的信息。
在Linux操作系统⾥有Ext2、Ext3、Linuxswap和VFAT四种格式 Ext2: Ext2是GNU/Linux系统中标准的⽂件系统。
这是Linux中使⽤最多的⼀种⽂件系统,它是专门为Linux设计的,拥有极快的速度和极⼩的CPU占⽤率。
Ext2既可以⽤于标准的块设备(如硬盘),也被应⽤在软盘等移动存储设备上。
Ext3: Ext3是Ext2的下⼀代,也就是保有Ext2的格式之下再加上⽇志功能。
Ext3是⼀种⽇志式⽂件系统(Journal File System),
最⼤的特点是:它会将整个磁盘的写⼊动作完整的记录在磁盘的某个区域上,以便有需要时回溯追踪。
当在某个过程中断时,系统可以根据这些记录直接回溯并重整被中断的部分,重整速度相当快。
该分区格式被⼴泛应⽤在Linux系统中。
Linux swap: 它是Linux中⼀种专门⽤于交换分区的swap⽂件系统。
Linux是使⽤这⼀整个分区作为交换空间。
⼀般这个swap格式的交换分区是主内存的2倍。
在内存不够时,Linux会将部分数据写到交换分区上。
VFAT: VFAT叫长⽂件名系统,这是⼀个与Windows系统兼容的Linux⽂件系统,⽀持长⽂件名,可以作为Windows与Linux交换⽂件的分区。
ext2 文件系统格式The Second Extended File System(ext2)文件系统是 Linux 系统中的标准 文件系统,是通过对 Minix 的文件系统进行扩展而得到的,其存取文件的性能 极好。
在 ext2 文件系统中,文件由 inode(包含有文件的所有信息)进行唯一标识。
一个文件可能对应多个文件名,只有在所有文件名都被删除后,该文件才会被 删除。
此外,同一文件在磁盘中存放和被打开时所对应的 inode 是不同的,并 由内核负责同步。
ext2 文件系统采用三级间接块来存储数据块指针,并以块 (block,默认为 1KB)为单位分配空间。
其磁盘分配策略是尽可能将逻辑相 邻的文件分配到磁盘上物理相邻的块中, 并尽可能将碎片分配给尽量少的文件, 以从全局上提高性能。
ext2 文件系统将同一目录下的文件(包括目录)尽可能 的放在同一个块组中,但目录则分布在各个块组中以实现负载均衡。
在扩展文 件时,会尽量一次性扩展 8 个连续块给文件(以预留空间的形式实现)。
2.1. 总体存储布局 请点评我们知道,一个磁盘可以划分成多个分区,每个分区必须先用格式化工具(例 如某种 mkfs 命令)格式化成某种格式的文件系统,然后才能存储文件,格式 化的过程会在磁盘上写一些管理存储布局的信息。
下图是一个磁盘分区格式化 成 ext2 文件系统后的存储布局。
图 1. ext2 文件系统的总体存储布局文件系统中存储的最小单位是块(Block),一个块究竟多大是在格式化时确 定的,例如 mke2fs 的-b 选项可以设定块大小为 1024、2048 或 4096 字节。
而上图中启动块(Boot Block)的大小是确定的,就是 1KB,启动块是由 PC 标准规定的,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用启 动块。
启动块之后才是 ext2 文件系统的开始, ext2 文件系统将整个分区划成若干 个同样大小的块组(Block Group),每个块组都由以下部分组成。
第九章_Ext2文件系统_ro机第九章Ext2文件系统9.1基本概念在上一章中,我们把Ext2、Minix、Ext等实际可使用的文件系统称为具体文件系统.具体文件系统管理的是一个逻辑空间,这个逻辑空间就象一个大的数组,数组的每个元素就是文件系统操作的基本单位——逻辑块,逻辑块是从0开始编号的,而且,逻辑块是连续的.与逻辑块相对的是物理块,物理块是数据在磁盘上的存取单位,也就是每进行一次I/O操作,最小传输的数据大小.我们知道数据是存储在磁盘的扇区中的,那么扇区是不是物理块呢?或者物理块是多大呢?这涉及到文件系统效率的问题.如果物理块定的比较大,比如一个柱面大小,这时,即使是1个字节的文件都要占用整个一个柱面,假设Linux环境下文件的平均大小为1K,那么分配32K的柱面将浪费97%的磁盘空间,也就是说,大的存取单位将带来严重的磁盘空间浪费.另一方面,如果物理块过小,则意味着对一个文件的操作将进行更多次的寻道延迟和旋转延迟,因而读取由小的物理块组成的文件将非常缓慢!可见,时间效率和空间效率在本质上是相互冲突的.因此,最优的方法是计算出Linux环境下文件的平均大小,然后将物理块大小定为最接近扇区的整数倍大小.在Ext2中,物理块的大小是可变化的,这取决于你在创建文件系统时的选择,之所以不限制大小,也正体现了Ext2的灵活性和可扩充性,一是因为要适应近年来文件的平均长度缓慢增长的趋势,二是为了适应不同的需要.比如,如果一个文件系统主要用于BBS服务,考虑到BBS上的文章通常很短小,所以,物理块选的小一点是恰当的.通常,Ext2的物理块占一个或几个连续的扇区,显然,物理块的数目是由磁盘容量等硬件因素决定的.逻辑块与物理块的关系类似于虚拟内存中的页与物理内存中的页面的关系.具体文件系统所操作的基本单位是逻辑块,只在需要进行I/O操作时才进行逻辑块到物理块的映射,这显然避免了大量的I/O操作,因而文件系统能够变得高效.逻辑块作为一个抽象的概念,它必然要映射到具体的物理块上去,因此,逻辑块的大小必须是物理块大小的整数倍,一般说来,两者是一样大的.通常,一个文件占用的多个物理块在磁盘上是不连续存储的,因为如果连续存储,则经过频繁的删除、建立、移动文件等操作,最后磁盘上将形成大量的空洞,很快磁盘上将无空间可供使用.因此,必须提供一种方法将一个文件占用的多个逻辑块映射到对应的非连续存储的物理块上去,Ext2等类文件系统是用索引节点解决这个问题的,具体实现方法后面再予以介绍.为了更好的说明逻辑块和物理块的关系,我们来看一个例子.假设用户要对一个已有文件进行写操作,用户进程必须先打开这个文件,file结构记录了该文件的当前位置.然后用户把一个指向用户内存区的指针和请求写的字节数传送给系统,请求写操作,这时系统要进行两次映射.一组字节到逻辑块的映射.这个映射过程就是找到起始字节到结束字节所占用的所有逻辑块号.这是因为在逻辑空间,文件传输的基本单位是逻辑块而不是字节.逻辑块到物理块的映射.这个过程必须要用到索引节点结构,该结构中有一个物理块指针数组,以逻辑块号为索引,通过这些指针找到磁盘上的物理块,具体实现将在介绍Ext2索引节点时再进行介绍.图9.1是由一组请求的字节到物理块的映射过程示意图.图9.1一组字节映射到物理块的示意图有了逻辑块和物理块的概念,我们也就知道通常所说的数据块是指逻辑块,以下没有特别说明,块或数据块指的是逻辑块.在Ext2中,还有一个重要的概念:片,它的作用是什么? 每个文件必然占用整数个逻辑块,除非每个文件大小都恰好是逻辑块的整数倍,否则最后一个逻辑块必然有空间未被使用,实际上,每个文件的最后一个逻辑块平均要浪费一半的空间,显然最终浪费的还是物理块.在一个有很多文件的系统中,这种浪费是很大的.Ext2使用片来解决这个问题.片也是一个逻辑空间中的概念,其大小在1K至4K之间,但片的大小总是不大于逻辑块.假设逻辑块大小为4K,片大小为1K,物理块大小也是1K,当你要创建一个3K大小的文件时,实际上分配给你了3个片,而不会给你一个逻辑块,当文件大小增加到4K时,文件系统则分配一个逻辑块给你,而原来的四个片被清空.如果文件又增加到5K时,则占用1个逻辑块和1个片.上述三种情况下,所占用的物理块分别是3个、4个、5个,如果不采用片,则要用到4个、4个、8个物理块,可见,使用片,减少了磁盘空间的浪费.当然,在物理块和逻辑块大小一样时,片就没有意义了.由上面分析也可看出:物理块大小100>12,所以要用到一次间接块,在一次间接块中查找第88项,此项内容就是对应的物理块的地址.而如果要找第1000个逻辑块对应的物理块,由于1000>256+12,所以要用到二次间接块了.索引节点的标志取下列几个值的可能组合.EXT2_SECRM_FL0x00000001完全删除标志.设置这个标志后,删除文件时,随机数据会填充原来的数据块.EXT2_UNRM_FL0x00000002可恢复标志.设置这个标志后,删除文件时,文件系统会保留足够信息,以确保文件仍能恢复EXT2_COMR_FL0x00000004压缩标志.设置这个标志后,表明该文件被压缩过.当访问该文件时,文件系统必须采用解压缩算法进行解压.EXT2_SYNC_FL0x00000008同步更新标志.设置该标志后,则该文件必须和内存中的内容保持一致,对这种文件进行异步输入、输出操作是不允许的.这个标志仅用于节点本身和间接块.数据块总是异步写入磁盘的.除了这几个常用标志外,还有12个标志就不一一介绍了.索引节点在磁盘上是经过编号的.其中,有一些节点有特殊用途,用户不能使用.这些特殊节点也在include/Linux/ext2_fs.h中定义.#defineEXT2_BAD_INO1该节点所对应的文件中包含着该文件系统中坏块的链接表#defineEXT2_ROOT_INO2该文件系统的根目录所对应的节点#defineEXT2_IDX_INO3ACL节点#defineEXT2_DATA_INO4ACL节点#defineEXT2_BOOT_LOADER_INO5用于引导系统的文件所对应的节点#defineEXT2_UNDEL_DIR_INO6文件系统中可恢复的目录对应的节点没有特殊用途的第一个节点号为11#defineEXT2_FIRST_INO11文件的类型、访问权限、用户标识号、用户组标识号等将在后面介绍.与Ext2超级块类似,当磁盘上的索引节点调入内存后,除了要填写VFS的索引节点外,系统还要根据它填写另一个数据结构,该结构叫ext2_inode_info,其作用也是为了存储特定文件系统自己的特性,它在include/Linux/ext2_fs_i.h中定义如下:structext2_inode_info{__u32i_data[15]数据块指针数组*/__u32i_flags;打开文件的方式*/__u32i_faddr;片的地址*/__u8i_frag_no;如果用到片,则是第一个片号*/__u8i_frag_size;片大小*/__u16i_osync;同步*/__u32i_file_acl;文件访问控制链表*/__u32i_dir_acl;目录访问控制链表*/__u32i_dtime;文件的删除时间*/__u32i_block_group;索引节点所在的块组号*//******以下四个域是用于操作预分配块的*__u32i_next_alloc_block;__u32i_next_alloc_goal;__u32i_prealloc_block;__u32i_prealloc_count;__u32i_dir_start_lookupinti_new_inode:1/*Isafreshlyallocatedinode*/};VFS索引节点中是没有物理块指针数组的域,这个Ext2特有的域在调入内存后,就必须保存在ext2_inode_info这个结构中.此外,片作为Ext2比较特殊的地方,在ext2_inode_info中也保存了一些相关的域.另外,Ext2在分配一个块时通常还要预分配几个连续的块,因为它判断这些块很可能将要被访问,所以采用预分配的策略可以减少磁头的寻道时间.这些用于预分配操作的域也被保存在ext2_inode_info结构中.9.2.4组描述符块组中,紧跟在超级块后面的是组描述符表,其每一项称为组描述符,是一个叫ext2_group_desc的数据结构,共32字节.它是用来描述某个块组的整体信息的. structext2_group_desc{__u32bg_block_bitmap;/*组中块位图所在的块号*/__u32bg_inode_bitmap;组中索引节点位图所在块的块号*/__u32bg_inode_table;/*组中索引节点表的首块号*/__u16bg_free_blocks_count;/*组中空闲块数*/__u16bg_free_inodes_count;/*组中空闲索引节点数*/__u16bg_used_dirs_count;/*组中分配给目录的节点数*/__u16bg_pad;填充,对齐到字*/__u32[3]bg_reserved;用null填充12个字节*/}每个块组都有一个相应的组描述符来描述它,所有的组描述符形成一个组描述符表,组描述符表可能占多个数据块.组描述符就相当于每个块组的超级块,一旦某个组描述符遭到破坏,整个块组将无法使用,所以组描述符表也像超级块那样,在每个块组中进行备份,以防遭到破坏.组描述符表所占的块和普通的数据块一样,在使用时被调入块高速缓存.9.2.5位图在Ext2中,是采用位图来描述数据块和索引节点的使用情况的,每个块组中都有两个块,一个用来描述该组中数据块的使用情况,另一个描述该组中索引节点的使用情况.这两个块分别称为数据块位图块和索引节点位图块.数据位图块中的每一位表示该组中一个块的使用情况,如果为0,则表示相应数据块空闲,为1,则表示已分配,索引节点位图块的使用情况类似.Ext2在安装后,用两个高速缓存分别来管理这两种位图块.每个高速缓存最多同时只能装入Ext2_MAX_GROUP_LOADED个位图块或索引节点块,当前该值定义为8,所以也应该采用一些算法来管理这两个高速缓存,Ext2中采用的算法类似于LRU算法.前面说过,ext2_sp_info结构中有四个域用来管理这两个高速缓存,其中s_block_bitmap_number[]数组中存有进入高速缓存的位图块号,而s_block_bitmap[]数组则存储了相应的块在高速缓存中的地址.s_inode_bitmap_number[]和s_inode_bitmap[]数组的作用类似上面.我们通过一个具体的函数来看Ext2是如何通过这四个域管理位图块高速缓存的.在Linux/fs/ext2/balloc.c 中,有一个函数load__block_bitmap,它用来调入指定的数据块位图块,下面是它的执行过程:如果指定的块组号大于块组数,出错,结束;通过搜索s_block_bitmap_number[]数组可知位图块是否已进入高速缓存,如果已进入,则结束,否则,继续; 如果块组数不大于Ext2_MAX_GROUP_LOADED,高速缓存可以同时装入所有块组的数据块位图块,不用采用什么算法,只要找到s_block_bitmap_number[]数组中第一个空闲元素,将块组号写入,然后将位图块调入高速缓存,最后将它在高速缓存中的地址写入s_block_bitmap[]数组中;如果块组数大于Ext2_MAX_GROUP_LOADED,则需要采用以下算法;首先通过s_block_bitmap_number[]数组判断高速缓存是否已满,若未满,则操作过程类似上一步,不同之处在于需要将s_block_bitmap_number[]数组各元素依次后移一位,而用空出的第一个元素存储块组号,s_block_bitmap[]也要做相同处理;如果高速缓存已满,则将s_block_bitmap[]数组最后一项所指的位图块从高速缓存中交换出去,然后调入所指定的位图块,最后对这两个数组作和上面相同的操作;可以看出,这个算法很简单,就是对两个数组的简单操作,只是在块组数大于Ext2_MAX_GROUP_LOADED时,要求数组的元素按最近访问的先后次序排列,显然,这样也是为了更合理的进行高速缓存的替换操作.9.2.6索引节点表及实例分析在两个位图块后面,就是索引节点表了,每个块组中的索引节点都存储在各自的索引节点表中,并且按索引节点号依次存储.索引节点表通常占好几个数据块,索引节点表所占的块使用时也像普通的数据块一样被调入块高速缓存.有了以上几个概念和数据结构后,我们分析一个具体的例子,来看看这些数据结构是如何配合工作的.在fs/ext2/inode.c中,有一个ext2_read_inode,用来读取指定的索引节点信息.其代码如下:voidext2_read_inode{structbuffer_head*bh;structext2_inode*raw_inode; unsignedlongblock_group; unsignedlonggroup_desc; unsignedlongdesc; unsignedlongblock; unsignedlongoffset;structext2_group_desc *gdp;if)||inode->i_ino>le32_to_cpu){ext2_error;gotobad_inode;}block_group/EXT2_INODES_PER_GROUP;if{ext2_error;gotobad_inode;}group_desc=block_group>>EXT2_DESC_PER_BLOCK_BITS; desc=block_group&1);bh=inode->i_sb->u.ext2_sb.s_group_desc[group_desc]; if{ext2_error;gotobad_inode;}gdp=bh->b_data;/**Figureouttheoffsetwithintheblockgroupinodetable*/offset=%EXT2_INODES_PER_GROUP) *EXT2_INODE_SIZE;block=le32_to_cpu+);if)){ext2_error;gotobad_inode;}offset&=-1);raw_inode=;inode->i_mode =le16_to_cpu; inode->i_uid=le16_to_cpu;inode->i_gid =le16_to_cpu; if)){inode->i_uid |=le16_to_cpui_gid|=le16_to_cpui_nlink=le16_to_cpu; inode->i_size =le32_to_cpu; inode->i_atime =le32_to_cpu; inode->i_ctime =le32_to_cpu;inode->i_mtime=le32_to_cpu;inode->u.ext2_i.i_dtime =le32_to_cpu;/*Wenowhaveenoughfieldstocheckiftheinodewasactiveornot.Thisis needed because nfsd might tryto access dead inodes *the testisthat same one thate2fsck usesNeilBrown 1999oct15*/if){/*thisinodeisdeleted*/brelse;gotobad_inode;}inode->i_blksize =PAGE_SIZE;/*ThistheoptimalIOsize,notthefsblocksize*/inode->i_blocks=le32_to_cpu;inode->i_version=++event;inode->u.ext2_i.i_flags =le32_to_cpu;inode->u.ext2_i.i_faddrle32_to_cpu;inode->u.ext2_i.i_frag_no =raw_inode->i_frag;inode->u.ext2_i.i_frag_size =raw_inode->i_fsize; inode->u.ext2_i.i_file_acl =le32_to_cpu;if)inode->i_size|=le32_to_cpu)u.ext2_i.i_dir_acl=le32_to_cpu;inode->i_generation=le32_to_cpu;inode->u.ext2_i.i_prealloc_count =0;inode->u.ext2_i.i_block_group =block_group;/**NOTE!Thein-memoryinodei_dataarrayisinlittle-endianorder*evenonbig-endianmachines: wedoNOT byteswap theblock numbers! */for/* Nothingtodo*/;elseif){inode->i_op=&ext2_file_inode_operations; inode->i_fop=&ext2_file_operations;inode->i_mapping->a_ops=&ext2_aops;}elseif){inode->i_op=&ext2_dir_inode_operations; inode->i_fop=&ext2_dir_operations; inode->i_mapping->a_ops=&ext2_aops;}elseif){ifinode->i_op=&ext2_fast_symlink_inode_operations; else{inode->i_op=&page_symlink_inode_operations; inode->i_mapping->a_ops=&ext2_aops;}}elseinit_special_inode);brelse;inode->i_attr_flags=0;if{inode->i_attr_flags|=A TTR_FLAG_SYNCRONOUS; inode->i_flags|=S_SYNC;}if{inode->i_attr_flags|=A TTR_FLAG_APPEND;inode->i_flags|=S_APPEND;}if{inode->i_attr_flags|=A TTR_FLAG_IMMUTABLE; inode->i_flags|=S_IMMUTABLE;}if{inode->i_attr_flags|=A TTR_FLAG_NOA TIME; inode->i_flags|=S_NOATIME;}return;bad_inode:make_bad_inode;return;}这个函数的代码有200多行,为了突出重点,下面是对该函数主要内容的描述:如果指定的索引节点号是一个特殊的节点号,或者小于第一个非特殊用途的节点号,即EXT2_FIRST_INO ,或者大于该文件系统中索引节点总数,则输出错误信息,并返回;用索引节点号整除每组中索引节点数,计算出该索引节点所在的块组号;即block_group=/Ext2_INODES_PER_GROUP找到该组的组描述符在组描述符表中的位置.因为组描述符表可能占多个数据块,所以需要确定组描述符在组描述符表的哪一块以及是该块中第几个组描述符. 即:group_desc=block_group>>Ext2_DESC_PER_BLOCK_BITS表示块组号整除每块中组描述符数,计算出该组的组描述符在组描述符表中的哪一块.我们知道,每个组描述符是32字节大小,在一个1K大小的块中可存储32个组描述符.块组号与每块中组的描述符数进行”与”运算,得到这个组描述符具体是该块中第几个描述符.即desc=block_group&-1).有了group_desc和desc,接下来在高速缓存中找这个组描述符就比较容易了:即:bh=inode->i_sb->u.ext2_sb.s_group_desc[group_desc],首先通过s_group_desc[]数组找到这个组描述符所在块在高速缓存中的缓冲区首部;然后通过缓冲区首部找到数据区,即gdp=bh->b_data.找到组描述符后,就可以通过组描述符结构中的bg_inode_tabl找到索引节点表首块在高速缓存中的地址:offset=%Ext2_INODES_PER_GROUP)*Ext2_INODE_SIZE,计算该索引节点在块中的偏移位置;block=le32_to_cpu+),计算索引节点所在块的地址;代码中le32_to_cpu、le16_to_cpu按具体CPU的要求进行数据的排列,在i386处理器上访问Ext2文件系统时这些函数不做任何事情.因为不同的处理器在存取数据时在字节的排列次序上有所谓”bigending”和”littleending”之分.例如,i386就是”littleending”处理器,它在存储一个16位数据0x1234时,实际存储的却是0x3412,对32位数据也是如此.这里索引节点号与块的长度都作为32位或16位无符号整数存储在磁盘上,而同一磁盘既可以安装在采用”little ending”方式的CPU机器上,也可能安装在采用”big ending”方式的CPU机器上,所以要选择一种形式作为标准.事实上,Ext2采用的标准为”littleending”,所以,le32_to_cpu、le16_to_cpu函数不作任何转换.计算出索引节点所在块的地址后,就可以调用sb_bread通过设备驱动程序读入该块.从磁盘读入的索引节点为ext2_Inode数据结构,前面我们已经看到它的定义.磁盘上索引节点中的信息是原始的、未经加工的,所以代码中称之为raw_inode,即raw_inode=与磁盘索引节点ext2_inode相对照,内存中VFS的inode结构中的信息则分为两部分,一部分是属于VFS层的,适用于所有的文件系统;另一部份则属于具体的文件系统,这就是inode中的那个union,因具体文件系统的不同而赋予不同的解释.对Ext2来说,这部分数据就是前面介绍的ext2_inode_info结构.至于代表着符号链接的节点,则并没有文件内容,所以正好用这块空间来存储链接目标的路径名.ext2_inode_info结构的大小为60个字节.虽然节点名最长可达255个字节,但一般都不会太长,因此将符号链接目标的路径名限制在60个字节不至于引起问题.代码中inode->u.*设置的就是Ext2文件系统的特定信息.接着,根据索引节点所提供的信息设置inode结构中的inode_operations结构指针和file_operations结构指针,完成具体文件系统与虚拟文件系统VFS之间的连接.目前2.4版内核并不支持存取控制表ACL,因此,代码中只是为之留下了位置,而暂时没做任何处理.另外,通过检查inode结构中的mode域来确定该索引节点是常规文件、目录、符号链接还是其他特殊文件而作不同的设置或处理.例如,对Ext2文件系统的目录节点,就将i_op和i_fop分配设置为ext2_dir_inode_operations和ext2_dir_operations.而对于Ext2常规文件,则除i_op和i_fop以外,还设置了另一个指针a_ops,它指向一个address_apace_operation结构,用于文件到内存空间的映射或缓冲.对特殊文件,则通过init_special_inode函数加以检查和处理.从这个读索引节点的过程可以看出,首先要寻找指定的索引节点,要找索引节点,必须先找组描述符,然后通过组描述符找到索引节点表,最后才是在这个索引节点表中找索引节点.当从磁盘找到索引节点以后,就要把其读入内存,并存放在VFS索引节点相关的域中.从这个实例的分析,读者可以仔细体会前面所介绍的各种数据结构的具体应用.9.2.7Ext2的目录项及文件的定位文件系统一个很重要的问题就是文件的定位,如何通过一个路径来找到一个文件的具体位置,这就要依靠ext2_dir_entry这个结构.1.Ext2目录项结构在Ext2中,目录是一种特殊的文件,它是由ext2_dir_entry这个结构组成的列表.这个结构是变长的,这样可以减少磁盘空间的浪费,但是,它还是有一定的长度方面的限制,一是文件名最长只能为255个字符.二是尽管文件名长度可以不限,但系统自动将之变成4的整数倍,不足的地方用null字符填充.目录中有文件和子目录,每一项对应一个ext2_dir_entry.该结构在include/Linux/ext2_fs.h中定义如下:/**Structureofadirectoryentry*/#defineEXT2_NAME_LEN255structext2_dir_entry{__u32inode;Inodenumber*/__u16rec_len;Directoryentrylength*/__u16name_len;Namelength*/charname[EXT2_NAME_LEN]Filename*/};这是老版本的定义方式,在ext2_fs.h中还有一种新的定义方式:/**Thenewversionofthedirectory entry.SinceEXT2structures are*storedinintelbyteorder,andthename_lenfieldcouldneverbe*than255chars,it’ssafetoreclaimtheextrabyteforthe*file_typefield.*/structext2_dir_entry_2{__u32inode;Inode number*/__u16rec_len;Directorylength*/__u8name_len;Namelength*/__u8file_type;charname[EXT2_NAME_LEN]Filename*/};其二者的差异在于,一是新版中结构名改为ext2_dir_entry_2;二是老版本中ext2_dir_entry中的name_len为无符号短整数,而新版中则改为8位的无符号字符,腾出一半用作文件类型.目前已定义的文件类型为:**Ext2directorytypes.Onlythelow3bitsareused.The*otherbitsarereservedfornow.*/enum{EXT2_FT_UNKNOWN, /*未知*/EXT2_FT_REG_FILE,/*常规文件*/EXT2_FT_DIR,/*目录文件*/EXT2_FT_CHRDEV,/*字符设备文件*/EXT2_FT_BLKDEV,/*块设备文件*/EXT2_FT_FIFO,/*命名管道文件*/EXT2_FT_SOCK,/*套接字文件*/EXT2_FT_SYMLINK,/*符号连文件*/EXT2_FT_MAX/*文件类型的最大个数*/};2.各种文件类型如何使用数据块我们说,不管哪种类型的文件,每个文件都对应一个inode结构,在inode结构中有一个指向数据块的指针i_blaock,用来标识分配给文件的数据块.但是Ext2所定义的文件类型以不同的方式使用数据块.有些类型的文件不存放数据,因此,根本不需要数据块,下面对不同文件类型如何使用数据块给予说明.常规文件常规文件时最常用的文件.常规文件在刚创建时是空的,并不需要数据块,只有在开始有数据时才需要数据块;可以用系统调用truncate清空一个常规文件.目录文件Ext2以一种特殊的方式实现了目录,这种文件的数据块中存放的就是ext2_dir_entry_2结构.如前所述,这个结构的最后一个域是可变长度数组,因此该结构的长度是可变的.在ext2_dir_entry_2结构中,因为rec_len域是目录项的长度,把它与目录项的起始地址相加就得到下一个目录项的起始地址,因此说,rec_len可以被解释为指向下一个有效目录项的指针.为了删除一个目录项,把ext2_dir_entry_2的inode域置为0并适当增加前一个有效目录项rec_len域的值就可以了.符号连如果符号连的路径名小于60个字符,就把它存放在索引节点的i_blaock域,该域是由15个4字节整数组成的数组,因此无需数据块.但是,如果路径名大于60个字符,就需要一个单独的数据块.设备文件、管道和套接字这些类型的文件不需要数据块.所有必要的信息都存放在索引节点中.3.文件的定位文件的定位是一个复杂的过程,我们先看一个具体的例子,然后再结合上面的数据结构具体介绍一下如何找到一个目录项的过程.如果要找的文件为普通文件,则可通过文件所对应的索引节点找到文件的具体位置,如果是一个目录文件,则也可通过相应的索引节点找到目录文件具体所在,然后再从这个目录文件中进行下一步查找,来看一个具体的例子.假设路径为/home/user1/file1,home和user1是目录名,而file1为文件名.为了找到这个文件,有两种途径,一是从根目录开始查找,二是从当前目录开始查找.假设我们从根目录查找,则必须先找到根目录的节点,这个节点的位置在VFS中的超级块中已经给出,然后可找到根目录文件,其中必有home所对应的目录项,由此可先找到home节点,从而home的目录文件,然后依次是user1的节点和目录文件,最后,在该目录文件中的file1目录项中找到file1的节点,至此,已经可以找到file1文件的具体所在了.目录中还有两个特殊的子目录:”.”和”..”,分别代表当前目录和父目录.它们是无法被删除的,其作用就是用来进行相对路径的查找.现在,我们来分析一下fs/ext2/dir.c中的函数ext2_find_entry,该函数从磁盘上找到并读入当前节点的目录项,其代码及解释如下:/**ext2_find_entry**findsanentryinthespecifieddirectorywiththewantedname.It* returns the pagein which the entry was found, andthe entry itself*.Pageis returned mapped andunlocked.*Entryisguaranteedtobevalid.*/typedefstructext2_dir_entry_2ext2_dirent; structext2_dir_entry_2*ext2_find_entry{constchar*name=dentry->d_;/*目录项名*/intnamelen=dentry->d_name.len;/*目录项名的长度*/ unsignedreclen=EXT2_DIR_REC_LEN;/*目录项的长度*/ unsignedlongstart,n;unsignedlongnpages=dir_pages;/*把以字节为单位的文件大小转换为物理页面数*/。
EXT2⽂件系统对⽂件系统⽽⾔,⽂件仅是⼀系列可读写的数据块。
⽂件系统并不需要了解数据块应该放到物理介质上什么位置。
这些都是设备驱动的任务。
⽆论何时,只要⽂件系统需要从包含它的块设备中读取信息或数据,它就将请求底层的设备驱动读取⼀个基本块⼤⼩整数倍的数据块。
EXT2⽂件系统将它所使⽤的逻辑分区划分成数据块组。
每个数据块组都将那些对⽂件系统完整性最重要的信息复制出来,同时将实际⽂件盒⽬录看做信息与数据块。
罗即⽂件系统管理的是⼀个逻辑空间,这个逻辑空间就像⼀个⼤的数组,数组的每个元素就是⽂件系统操作的基本单位——逻辑块。
逻辑块是从0开始编号的,⽽且,逻辑块是连续的,逻辑块相对的是物理块。
通常,EXT2的物理块占⼀个或⼏个连续的扇区。
⼀般⽽⾔,只有块组0的超级块才读⼊内存,其他块组的超级块仅仅作为备份。
在系统运⾏期间,要将超级块复制到内存系统缓冲区。
块位图和节点位图在EXT2⽂件系统中,采⽤位图描述数据块和索引节点的使⽤情况,每个块组中占⽤两个块,即⼀个⽤来描述该数据块的使⽤情况,另⼀个描述该组索引节点的使⽤情况。
这两个块分别称为数据位图块和索引节点位图块。
数据位图块中的每⼀位表⽰该块组中的每⼀个块的使⽤情况,如果为0,则表⽰相应数据块空闲,如果是1,则表⽰已分配。
索引节点表每个块组中的索引节点都存储在各⾃的索引节点表中,并且按索引节点号依次存储。
索引节点表通常占好⼏个数据块,索引节点表所占的块使⽤时也想普通的数据块⼀样被调⼊块⾼速缓存。
EXT2整个磁盘的逻辑结构如图所⽰:EXT2⽂件系统的⼏个数据结构1 EXT2超级块超级块中包含了描述⽂件系统基本尺⼨和形态的信息。
⽂件系统管理器利⽤他们来使⽤和维护⽂件系统。
EXT2超级块是⽤来描述EXT2⽂件系统整体信息的数据结构,是EXT2的核⼼所在。
超级块经函数ext2_fill_supter读⼊后,⼜在内存中建⽴⼀个映像super_block.u.ext2_sb_info结构。
ext2文件系统总体存储布局我们知道,一个磁盘可以划分成多个分区,每个分区必须先用格式化工具(例如某种mkfs命令)格式化成某种格式的文件系统,然后才能存储文件,格式化的过程会在磁盘上写一些管理存储布局的信息。
下图是一个磁盘分区格式化成ext2文件系统后的存储布局。
图 29.2. ext2文件系统的总体存储布局文件系统中存储的最小单位是块(Block),一个块究竟多大是在格式化时确定的,例如mke2fs 的-b选项可以设定块大小为1024、2048或4096字节。
而上图中启动块(Boot Block)的大小是确定的,就是1KB,启动块是由PC标准规定的,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用启动块。
启动块之后才是ext2文件系统的开始,ext2文件系统将整个分区划成若干个同样大小的块组(Block Group),每个块组都由以下部分组成。
超级块(Super Block)描述整个分区的文件系统信息,例如块大小、文件系统版本号、上次mount的时间等等。
超级块在每个块组的开头都有一份拷贝。
块组描述符表(GDT,Group Descriptor Table)由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。
每个块组描述符(Group Descriptor)存储一个块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等。
和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝。
通常内核只用到第0个块组中的拷贝,当执行e2fsck检查文件系统一致性时,第0个块组中的超级块和块组描述符表就会拷贝到其它块组,这样当第0个块组的开头意外损坏时就可以用其它拷贝来恢复,从而减少损失。
块位图(Block Bitmap)一个块组中的块是这样利用的:数据块(Data Block)存储所有文件的数据,比如某个分区的块大小是1024字节,某个文件是2049字节,那么就需要三个数据块来存,即使第三个块只存了一个字节也需要占用一个整块;超级块、块组描述符表、块位图、inode位图、inode表这几部分存储该块组的描述信息。
那么如何知道哪些块已经用来存储文件数据或其它描述信息,哪些块仍然空闲可用呢?块位图就是用来描述整个块组中哪些块已用哪些块空闲的,它本身占一个块,其中的每个bit代表本块组中的一个块,这个bit为1表示该块已用,这个bit为0表示该块空闲可用。
为什么用df命令统计整个磁盘的已用空间非常快呢?因为只需要查看每个块组的块位图即可,而不需要搜遍整个分区。
相反,用du命令查看一个较大目录的已用空间就非常慢,因为不可避免地要搜遍整个目录的所有文件。
与此相联系的另一个问题是:在格式化一个分区时究竟会划出多少个块组呢?主要的限制在于块位图本身必须只占一个块。
用mke2fs格式化时默认块大小是1024字节,可以用-b参数指定块大小,现在设块大小指定为b字节,那么一个块可以有8b个bit,这样大小的一个块位图就可以表示8b个块的占用情况,因此一个块组最多可以有8b个块,如果整个分区有s个块,那么就可以有s/(8b)个块组。
格式化时可以用-g参数指定一个块组有多少个块,但是通常不需要手动指定,mke2fs工具会计算出最优的数值。
inode位图(inode Bitmap)和块位图类似,本身占一个块,其中每个bit表示一个inode是否空闲可用。
inode表(inode Table)我们知道,一个文件除了数据需要存储之外,一些描述信息也需要存储,例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访问时间等,也就是ls -l命令看到的那些信息,这些信息存在inode中而不是数据块中。
每个文件都有一个inode,一个块组中的所有inode 组成了inode表。
inode表占多少个块在格式化时就要决定并写入块组描述符中,mke2fs格式化工具的默认策略是一个块组有多少个8KB就分配多少个inode。
由于数据块占了整个块组的绝大部分,也可以近似认为数据块有多少个8KB就分配多少个inode,换句话说,如果平均每个文件的大小是8KB,当分区存满的时候inode表会得到比较充分的利用,数据块也不浪费。
如果这个分区存的都是很大的文件(比如电影),则数据块用完的时候inode会有一些浪费,如果这个分区存的都是很小的文件(比如源代码),则有可能数据块还没用完inode就已经用完了,数据块可能有很大的浪费。
如果用户在格式化时能够对这个分区以后要存储的文件大小做一个预测,也可以用mke2fs的-i 参数手动指定每多少个字节分配一个inode。
数据块根据不同的文件类型有以下几种情况∙对于常规文件,文件的数据存储在数据块中。
∙∙对于目录,该目录下的所有文件名和目录名存储在数据块中,注意文件名保存在它所在目录的数据块中,除文件名之外,ls -l命令看到的其它信息都保存在该文件的inode中。
注意这个概念:目录也是一种文件,是一种特殊类型的文件。
∙∙对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。
∙∙设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode 中。
∙现在做几个小实验来理解这些概念。
例如在home目录下ls -l:$ ls -ltotal 32drwxr-xr-x 114 akaedu akaedu 12288 2008-10-25 11:33 akaedudrwxr-xr-x 114 ftp ftp 4096 2008-10-25 10:30 ftpdrwx------ 2 root root 16384 2008-07-04 05:58 lost+found为什么各目录的大小都是4096的整数倍?因为这个分区的块大小是4096,目录的大小总是数据块的整数倍。
为什么有的目录大有的目录小?因为目录的数据块保存着它下边所有文件和目录的名字,如果一个目录中的文件很多,一个块装不下这么多文件名,就可能分配更多的数据块给这个目录。
再比如:$ ls -l /dev......prw-r----- 1 syslog adm 0 2008-10-25 11:39 xconsolecrw-rw-rw- 1 root root 1, 5 2008-10-24 16:44 zeroxconsole文件的类型是p(表示pipe),是一个FIFO文件,后面会讲到它其实是一块内核缓冲区的标识,不在磁盘上保存数据,因此没有数据块,文件大小是0。
zero文件的类型是c,表示字符设备文件,它代表内核中的一个设备驱动程序,也没有数据块,原本应该写文件大小的地方写了1, 5这两个数字,表示主设备号和次设备号,访问该文件时,内核根据设备号找到相应的驱动程序。
再比如:$ touch hello$ ln -s ./hello halo$ ls -ltotal 0lrwxrwxrwx 1 akaedu akaedu 7 2008-10-25 15:04 halo -> ./hello-rw-r--r-- 1 akaedu akaedu 0 2008-10-25 15:04 hello文件hello是刚创建的,字节数为0,符号链接文件halo指向hello,字节数却是7,为什么呢?其实7就是“./hello”这7个字符,符号链接文件就保存着这样一个路径名。
再试试硬链接:$ ln ./hello hello2$ ls -ltotal 0lrwxrwxrwx 1 akaedu akaedu 7 2008-10-25 15:08 halo -> ./hello-rw-r--r-- 2 akaedu akaedu 0 2008-10-25 15:04 hello-rw-r--r-- 2 akaedu akaedu 0 2008-10-25 15:04 hello2hello2和hello除了文件名不一样之外,别的属性都一模一样,并且hello的属性发生了变化,第二栏的数字原本是1,现在变成2了。
从根本上说,hello和hello2是同一个文件在文件系统中的两个名字,ls -l第二栏的数字是硬链接数,表示一个文件在文件系统中有几个名字(这些名字可以保存在不同目录的数据块中,或者说可以位于不同的路径下),硬链接数也保存在inode 中。
既然是同一个文件,inode当然只有一个,所以用ls -l看它们的属性是一模一样的,因为都是从这个inode里读出来的。
再研究一下目录的硬链接数:$ mkdir a$ mkdir a/b$ ls -ld adrwxr-xr-x 3 akaedu akaedu 4096 2008-10-25 16:15 a$ ls -la atotal 20drwxr-xr-x 3 akaedu akaedu 4096 2008-10-25 16:15 .drwxr-xr-x 115 akaedu akaedu 12288 2008-10-25 16:14 ..drwxr-xr-x 2 akaedu akaedu 4096 2008-10-25 16:15 b$ ls -la a/btotal 8drwxr-xr-x 2 akaedu akaedu 4096 2008-10-25 16:15 .drwxr-xr-x 3 akaedu akaedu 4096 2008-10-25 16:15 ..首先创建目录a,然后在它下面创建子目录a/b。
目录a的硬链接数是3,这3个名字分别是当前目录下的a,a目录下的.和b目录下的..。
目录b的硬链接数是2,这两个名字分别是a目录下的b和b目录下的.。
注意,目录的硬链接只能这种方式创建,用ln命令可以创建目录的符号链接,但不能创建目录的硬链接。
实例剖析如果要格式化一个分区来研究文件系统格式则必须有一个空闲的磁盘分区,为了方便实验,我们把一个文件当作分区来格式化,然后分析这个文件中的数据来印证上面所讲的要点。
首先创建一个1MB的文件并清零:$ dd if=/dev/zero of=fs count=256 bs=4K我们知道cp命令可以把一个文件拷贝成另一个文件,而dd命令可以把一个文件的一部分拷贝成另一个文件。
这个命令的作用是把/dev/zero文件开头的1M(256×4K)字节拷贝成文件名为fs 的文件。
刚才我们看到/dev/zero是一个特殊的设备文件,它没有磁盘数据块,对它进行读操作传给设备号为1, 5的驱动程序。