第十一章EXT2文件系统
EXT2是一个完全与LINUX兼容的文件系统,这一章在简要EXT2-EXT4的当前状况之后,又用编程示例各种数据结构与如何进行相关的实现还展示了如何通过虚拟磁盘mount-root来构建基本文件系统,将文件系统的实现分为了三个级别并分别介绍。
EXT2文件系统
EXT2第二代扩展文件系统(英语:second extended filesystem,缩写为 ext2),是LINUX内核所用的文件系统。它开始由Rémy Card设计,用以代替ext,于1993年1月加入linux核心支持之中。ext2 的经典实现为LINUX内核中的ext2fs文件系统驱动,最大可支持2TB的文件系统,至linux核心2.6版时,扩展到可支持32TB。而EXT3为其拓展,增加了一个日志文件,用来记录文件系统的更改记录。EXT4又作为EXT3的最新扩展,改为分配连续的磁盘块区,称为区段。
EXT2文件系统数据结构
通过mkfs创建虚拟磁盘
在Linux下,指令
mkd2fs [-b blksize -N ninodes] device nblocks
在设备上创建一个带有nblocks个块和ninodes个索引节点的EXT2文件系统,设备可以是真实设备,也可以是虚拟磁盘文件。
虚拟磁盘布局
上述EXT2文件系统的布局如图:
- B0:引导块,文件系统不会使用它。它用于容纳从磁盘引导操作系统的引导程序。
超级块
- B1:超级块,用于容纳关于整个文件系统的信息。
部分重要字段:
块组描述符
- B2:块组描述符块。EXT2将磁盘块分为几个组。每个组有8192个块(硬盘上的大小为32k)。每组用一个块组描述符结构体描述。
块和索引节点位图
- B8:块位图。位图用于分配和回收项。
- B9:索引节点位图。一个索引节点就是用于代表一个文件的数据结构。
- B10:索引(开始)节点块。
主要索引节点字段:
i_block[15]数组包含指向文件磁盘块的指针,这些磁盘块有:
直接块:i_block[0]至i_block[11],指向直接磁盘块;
间接块:i_block[12]指向一个包含256个块编号生物磁盘块,每个块编号指向一个磁盘块;
双重间接块:i_block[13]指向一个指向256个块的块,每个块指向256个磁盘块;
三重间接块:i_block[14],可以忽略。
邮差算法
一个城市有M个街区,编号从0到M-1.每个街区有N座房子,编号从0到N-1.每座房子有一个唯一的街区地址,用(街区,房子)表示。已知某个街区地址BA=(街区,房子),怎么把他转换为线性地址LA。
Linear_address LA=N*block + house
Block_address BA=(LA/N,LA%N)
C语言中的Test- Set-Clear位
我们可用C语言结合使用邮差算法和位屏蔽来进行下面的操作
.TST a bit to 1 or 0 : if (buf[i] & (i<<j))
.SET a bit to 0 : (buf[i] |= (i<<j));
.CLR a bit to 0 : (buf[i] &= (i<<j));
注意,一些C语言编译器允许在结构体中指定位,如:
struct bits{
unsigned int bit0 : 1;// bit0 field is a single bit
unsigned int bit123 :3; // bit123 field is a range of 3 bits
unsigned int otherbits: 27; // other bits field has 27 bits
unsigned int bit31 1 ;// bit31 is the highest bit
}var;
该结构体将var.定义为一个32位无符号整数,具有单独的位或位范围。那么,var.bit0=0;将1赋值给第0位,则有var.bit123=5;将101赋值给第1位到第3位等。但是,生成的代码仍然依赖于邮差算法和位屏蔽来访问各个位。我们可以用邮差算法直接操作位图中的位,无须定义复杂的C语言结构体。
将索引节点号转换为磁盘上的索引节点
在 EXT2文件系统中,每个文件都有一个唯一的索引节点结构。在文件系统磁盘上,索引节点从 inode table 块开始。每个磁盘块包含
INODES_PER_BLOCK = BLOCK_SIZE/sizeof(INODE)
个索引节点。每个索引节点都有一个唯一的索引节点号,ino=1,2,…,从1开始线性计数。
已知一个ino,如1234,那么哪个磁盘块包含该索引节点,以及哪个索引节点在该块中呢?我们需要知道磁盘块号,因为需要通过块来读/写一个真正的磁盘。
block =(ino - 1)/INODES_PER_BLOCK + inode_table;
inode =(ino - 1)% INODES_PER_BLOCK;
同样,将EXT2 文件系统中的双重和三重间接逻辑块号转换为物理块号也依赖于邮差算法。
将线性磁盘块号转换为 CHS=(柱面、磁头、扇区)格式∶软盘和旧硬盘使用CHS寻址,但文件系统始终使用线性块寻址。在调用BIOS INT13时,可用该算法将磁盘块号转换为CHS。
EXT2文件系统的实现
文件系统的结构
图11.7显示了EXT2文件系统的内部结构。标签(1)至(5)对结构图进行了说明。
(1)是当前运行进程的 PROC结构体。在实际系统中,每个文件操作都是由当前执行的进程决定的。每个进程都有一个cwd,指向进程当前工作目录(CWD)的内存索引节点s 它还有一个文件描述符数组 fd【】,指向打开的文件实例。
(2)是文件系统的根指针。它指向内存中的根索引节点。当系统启动时,选择其中一个设备作为根设备,它必须是有效的 EXT2文件系统。根设备的根索引节点(inode #2)作为文件系统的根(/)加载到内存中。该操作称为"挂载根文件系统"。
(3)是一个openTable条目。当某个进程打开文件时,进程 fd数组的某个条目会指向openTable,openTable 指向打开文件的内存索引节点。
(4)是内存索引节点。当需要某个文件时,会把它的索引节点加载到minode槽中以供使用。因为索引节点是唯一的,所以在任何时候每个索引节点在内存中都只能有一个副本。在minode中,(dev; ino)会确定索引节点的来源,以便将修改后的索引节点写回磁盘。refCount字段会记录使用minode 的进程数。
dirty字段表示索引节点是否已被修改。挂载标志表示索引节点是否已被挂载,如果已被挂载,mntabPtr将指向挂载文件系统的挂载表条目。lock字段用于确保内存索引节点一次只能由一个进程访问,例如在修改索引节点时,或者在读/写操作过程中。
(5)是已挂载的文件系统表。对于每个挂载的文件系统,挂载表中的条目用于记录挂载的文件系统信息,例如挂载的文件系统设备号。在挂载点的内存索引节点中、挂载标志打开,mntabPtr指向挂载表条目。在挂载表条目中,mntPointPtr指向挂载点的内存索引节点。后面将会讲到,这些双链接指针允许我们在遍历文件系统树时跨越挂载点。此外,挂载表条目还可能包含挂载文件系统的其他信息,例如超级块、块组描述符、位图和索引节点启动块的值,以便快速访问。如果任何缓存项有修改,当卸载设备时,必须将它们写回设备。
文件系统的级别
文件系统的实现分为三个级别。每个级别处理文件系统的不同部分。这使得实现过程模块化,更容易理解。在文件系统的实现过程中,FS目录包含实现 EXT2 文件系统的文件。文件结构如下。
- 第1级别实现了基本文件系统树,包含以下文件,实现了指定函数。
使用第1级别FS函数的用户命令程序有:mkdir,creat,mkond,rmdir,link,symlink,rm,ls,cd和pwd等
- 第2级别实现了文件内容的读/写函数。
- 第3级别实现了文件系统的挂载、卸载和文件保护。
基本文件系统
- type.h文件
这类文件包含 EXT2文件系统的数据结构类型,比如超块、组描述符、索引节点和目录条目结构。此外,它还包含打开文件表、挂载表、PROC结构体和文件系统常数。 - global.c文件
这类文件包含文件系统的全局变量
问题与解决
磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个分区。 为什么需要进行『格式化』呢?
这是因为每种操作系统所配置的文件属性/权限并不相同, 为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利用的『文件系统格式(filesystem)』。
传统的磁盘与文件系统之应用中,一个分区就是只能够被格式化成为一个文件系统,所以我们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如我们常听到的LVM与软件磁盘阵列(software raid), 这些技术可以将一个分区格式化为多个文件系统(例如LVM),也能够将多个分区合成一个文件系统(LVM, RAID)! 所以说,目前我们在格式化时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区。
那么文件系统是如何运行的呢?
这与操作系统的文件数据有关。较新的操作系统的文件数据除了文件实际内容外, 通常含有非常多的属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。 文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到 data block 区块中。 另外,还有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。
每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:
superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量, 以及文件系统的格式与相关信息等;
inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
block:实际记录文件的内容,若文件太大时,会占用多个 block。
总结
EXT2文件系统