EXT2文件系统
EXT2文件系统数据结构
- 通过mkfs创建虚拟磁盘
在Linux下,命令
mke2fs [-b blksize -N inodes] device blocks
在设备上创建一个带有nblocks个块和 inodes个索引节点的EXT2文件系统。设备可以是真实设备,也可以是虚拟磁盘文件。如果未指定 E blksize,则默认块大小为1KB。如果未指定 ninnies,mke2s将根据 blocks计算一个默认的 I inodes数。得到的EXT2文件系统可在 Linux中使用。
dd if=/dev/zero of=vdisk bs=1024 count=1440
mke2fs vdisk 1440
在名为vdisk的虚拟磁盘文件上创建一个EXT2文件系统,有1440个大小为1KB的块。
- 块组描述符
Bock#2:块组描述符块eXT2将磁盘块分成几个组。
每个组有8192个块(硬盘上的大小为32K)每组用一个块组描述符结构体来描述由于一个虚拟软盘(FD)只有1440个块,B2就只包含一个块组描述符。其余的都是0在有大量块组的硬盘上,块组描述符可以跨越多个块。
块组描述符中最重要的字段是bgblock bitmap、 bg inode bitmap和 bg inode table,它们分别指向块组的块位图、索引节点位图和索引节点起始块。
- 索引节点
每个文件都用一个128字节(EXT4中是256字节)的唯一索引节点结构体表示。下面列出了主要索引节点字段。block[15]数组包含指向文件磁盘块的指针,这些磁盘块有
-
直接块: i block[0]至 i block[,指向直接磁盘块。
-
间接块: i block[12]指向一个包含256个块编号(于1 KB BLKSIZE)的磁盘块,每个块编号指向一个磁盘块。
-
双重间接块: i block[13指向一个指向256个块的块,每个块指向256个磁盘块。
-
三重间接块: i block[11是三重间接块。对于“小型”EXT2文件系统,可以忽略它。
索引节点大小(128或256)用于平均分割块大小(1B或4KB),所以,每个索引节点块都包含整数个索引节点。在简单的EXT2文件系统中,索引节点的数量是184个(inux默认值)。索引节点块数等于184/8=23个。
因此,索引节点块为B10至B32。每个索引节点都有一个唯一的索引节点编号,即索引节点在索引节点块上的位置+1。注意,索引节点位置从0开始计数,而索引节点编号从1开始计数。0索引节点编号表示没有索引节点根目录的索引节点编号为2。同样,磁盘块编号也从1开始计数,因为文件系统从未使用块0。块编号0表示没有磁盘块。
- 数据块
紧跟在索引节点块后面的是文件存储数据块。
遍历算法
-
读取超级块。检查幻数 s magic(0xEF53),验证它确实是EXT2FS。
-
读取块组描述符块(1+ s first data block),以访问组0描述符。从块组描述符的bg inode table条目中找到索引节点的起始块编号,并将其称为 InodesBegin Block
-
读取 Inode Begin Block,获取/的索引节点,即 INODE#2。
-
将路径名标记为组件字符串,假设组件数量为n。例如,如果路径名=/ab/c,则组件字符串是“a”“b"“c”,其中n=3。用nme[0],name1],…,name[n-1]来表示组件。
-
从3中的根索引节点开始,在其数据块中搜索name[0]为简单起见,我们可以假设某个目录中的条目数量很少,因此一个目录索引节点只有12个直接数据块。有了这个假设,就可以在12个(非零)直接块中搜索nme[0]。
文件系统的结构
-
当前运行进程的PROC结构体。在实际系统中,每个文件操作都是由当前执行的进程决定的每个进程都有一个cwd,指向进程当前工作目录(CWD)的内存索引节点它还有一个文件描述符数组fd,指向打开的文件实例。
-
文件系统的根指针。它指向内存中的根索引节点。当系统启动时,选择其中一个设备作为根设备,它必须是有效的EXT2文件系统根设备的根索引节点( inode#2)作为文件系统的根加载到内存中该操作称为“挂载根文件系统”
-
一个 open Table条目。当某个进程打开文件时,进程fd数组的某个条目会指向openTable, open Table指向打开文件的内存索引节点内存索引节点。当需要某个文件时,会把它的索引节点加载到 minde槽中以供使用。因为索引节点是唯一的,所以在任何时候每个索引节点在内存中都只能有一个副本。在 minde中,(dev,ino)会确定索引节点的来源,以便将修改后的索引节点写回磁盘refCount字段会记录使用 inode的进程数。
-
drty字段表示索引节点是否已被修改。挂载标志表示索引节点是否已被挂载,如果已被挂载, mntabPtr将指向挂载文件系统的挂载表条目lck字段用于确保内存索引节点一次只能由一个进程访问。
-
是已挂载的文件系统表。对于每个挂载的文件系统,挂载表中的条目用于记录挂载的文件系统信息,例如挂载的文件系统设备号。在挂载点的内存索引节点中,挂载标志打开, mniabPtr指向挂载表条目。在挂载表条目中, mntPointPtr指向挂载点的内存索引节点后面将会讲到,这些双链接指针允许我们在遍历文件系统树时跨越挂载点。
- 此外,挂载表条目还可能包含挂载文件系统的其他信息,例如超级块、块组描述符、位图和索引节点启动块的值,以便快速访问。如果任何缓存项有修改,当卸载设备时,必须将它们写回设备。
索引节点的一般使用方式
-
更改目录( chdir):iget新目录的 minde,但是iput旧目录的 I minde
-
打开(open):iget文件的 inode,当文件关闭时释放
-
挂载( mount)):iget挂载点的 minde,稍后通过卸载释放。
mkdir算法
mkdir命令
mkdir pathname
创建了一个带路径名的新目录。将新目录的权限位设置为默认值0755(所有人可以访问和读写,其他人可以访问但只能读取)。
要创建一个目录,我们需要从索引节点位图中分配一个索引节点,并从块位图中分配一个磁盘块,分配操作依赖于测试。为了保持文件系统的一致性,分配一个索引节点后,必须将超级块和组块描述符中的空闲索引节点计数减1。同样,分配一个磁盘块后,也必须将超级块和块组描述符中的空闲块数减1。
文件系统项目的扩展
简单的EXT2文件系统使用1KB块大小,只有一个磁盘块组它可以轻松进行以下扩展。
-
多个组:组描述符的大小为32字节对于1KB大小的块,一个块可能包含
1024/32=32组描述符。32个组的文件系统大小可以扩展为32*8=256MB -
4KB大小的块:对于4KB大小的块和一个组,文件系统大小应为48=32MB。
对于一个组描述符块,文件系统可能有128个组,可将文件系统大小扩展到12832=4GB
对于2个组描述符块,文件系统大小为8GB等。大多数扩展都很简单,适合用于编程项目。 -
管道文件:管道可实现为普通文件,这些文件遵循管道的读/写协议。此方案的优点是:它统一了管道和文件索引节点,并允许可被不相关进程使用的命名管道。为支持快速读/写操作,管道内容应在内存中,比如在 RAMdisk中。必要时,读者可将命名管道实现为FIFO文件。
-
I/O缓冲:在编程项目中,每个磁盘块都是接读写的。这会产生过多的物理磁盘I/O操作。为提高效率,实际文件系统通常使用一系列I缓冲区作为磁盘块的缓存内存。文件系统的IO缓冲将会在第12章中讨论,但是可把它合并到文件系统。
问题与解决思路
实践内容与截图