学习笔记5
第十一章
一、EXT2文件系统数据结构
1、通过mkfs创建虚拟磁盘
在Linux下命令:
mke2fs[-b blksize -N ninodes] device nblocks
在设备上创建一个带有nblocks个块(每个块大小为blksize字节)和ninodes个索引节点的EXT2文件系统。
2、虚拟磁盘布局
上述EXT2文件系统的布局如图所示
3、超级块
Block#1:超级块(在磁盘分区中字节偏移量为1024) B1是超级块,用于容纳整个文件系统的信息。
大多数超级块字段的含义都非常明显。只有少数几个字段需要详细解释。
s_first_data_block : 0表示4KB块大小,1表示 1KB块大小。它用于确定块组描述符的起始块,即s_first_data_block +1。
s_log_block_size :确定文件块大小,为1KB*(2**s_log_block_size),例如:0表示lKB块大小,1表示2KB块大小,2表示4KB块大小等。最常用的块大小是用于小文件系统的1KB和用于大文件系统的4KB.
s_mnt_count : 已挂载文件系统的次数。当挂载计数达到max_mnt_count时,fsck 会话将被迫检查文件系统的一致性。
s_magic:标识文件系统类型的幻数。EXT2/3/4文件系统的幻数是0xEF53。
4、块组描述符
Block#2:块组描述符块(硬盘上的s_first_data_block+1) EXT2将磁盘块分成几个组。每个组有8192个块(硬盘上的大小为32K)。每组用一个块组描述符结构体来描述。
5、索引(开始)节点:每个文件都用一个128字节的唯一索引节点结构体表示。
在i_mode字段中,前4位指定了文件类型,接下来三位ugs表示文件的特殊用法。最后9位是用于文件保护的rwx权限位。
i_size字段表示文件大小(以字节为单位)。各时间字段表示自1970年1月1日0时0分0秒以来经过的秒数。所以,每个时间字段都是一个非常大的无符号整数。可借助以下库函数将它们转换为日历形式:
char *ctime(&time_field)
将指针指向时间字段,然后返回一个日历形式的字符串
6、目录条目
目录包含dir_entry结构,即
7.邮差算法应用
C语言中的Test-Set-Clear位
注意,一些 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,那么哪个磁盘块包含该索引节点,以及哪个索引节点在该块中呢?我们需要知道磁盘块号,因为需要通过块来读/写一个真正的磁盘。
7、遍历EXT2文件系统树
8、文件系统的结构
(1)是当前运行进程的PROC结构体;
(2)是文件系统的根指针;
(3)是一个openTable条目;
(4)是内存索引节点;
(5)是已挂载的文件系统表。
9、基本文件系统
type.h文件
这类文件包含EXT2文件系统的数据结构类型,比如超块、组描述符、索引节点和目录条目结构。此外,它还包含打开文件表、挂载表、PROC结构体和文件系统常数。
global.c文件
这类文件包含文件系统的全局变量。全局变量的例子有:
MINODE minode [NMINODE]; // in memory INODEs
MTABLE mtable [NMTABLE]; // mount tables
OFT oft [NOFT]; // Opened file instance
PROC proc[NPROC]PROC ] // PROC structures
PROC *running; // current executing
10、mount-root
mount_root.c文件:该文件包含mount_root()函数,在系统初始化期间调用该函数来挂载根文件系统。它读取根设备的超级块,以验证该设备是否为有效的EXT2文件系统。然后,它将根设备的根INODE ( ino = 2)加载到minode中,并将根指针设置为根minode。它还将所有进程的当前工作目录设置为根minode。分配一个挂载表条目来记录挂载的根文件系统。根设备的一些关键信息,如 inode和块的数量、位图的起始块和inode,表,也记录在挂载表中,以便快速访问。
11、文件系统项目的扩展
(1)多个组:组描述符的大小为32字节。对于1KB大小的块,一个块可能包含1024/32=32组描述符。32个组的文件系统大小可以扩展为328=256MB。
(2)4KB大小的块:对于4KB大小的块和一个组,文件系统大小应为48=32MB。对于一个组描述符块,文件系统可能有128个组,可将文件系统大小扩展到128*32=4GB。对于2个组描述符块,文件系统大小为8GB等。大多数扩展都很简单,适合用于编程项目。
(3)管道文件:管道可实现为普通文件,这些文件遵循管道的读/写协议。此方案的优点是;它统一了管道和文件索引节点,并允许可被不相关进程使用的命名管道。为支持快速读/写操作,管道内容应在内存中,比如在 RAMdisk中。必要时,读者可将命名管道实现为FIFO文件。
(4)I/O缓冲:在编程项目中,每个磁盘块都是直接读写的。这会产生过多的物理磁盘I/O操作。为提高效率,实际文件系统通常使用一系列I/O缓冲区作为磁盘块的缓存内存。文件系统的I/O缓冲将会在第12章中讨论,但是可以把它合并到文件系统项目中。
实践部分
练习11.10:实现函数mkdir于rmdir