信息安全系统实现与设计第六周——《Unix/Linux系统编程》第十一章自学
第十一章 EXT2 文件系统
EXT2是一个完全与LINUX兼容的文件系统,这一章在简要EXT2-EXT4的当前状况之后,又用编程示例各种数据结构与如何进行相关的实现还展示了如何通过虚拟磁盘mount-root来构建基本文件系统,将文件系统的实现分为了三个级别并分别介绍。
11.1 EXT2 文件系统
EXT2第二代扩展文件系统(英语:second extended filesystem,缩写为 ext2),是LINUX内核所用的文件系统。它开始由Rémy Card设计,用以代替ext,于1993年1月加入linux核心支持之中。
而EXT3为其拓展,增加了一个日志文件,用来记录文件系统的更改记录。
EXT4又作为EXT3的最新扩展,改为分配连续的磁盘块区,称为区段。
11.2 EXT2文件系统数据结构
这一部分在我之前所写的第七章学习笔记的7.4中(https://www.cnblogs.com/jcy1171553035/p/15391164.html)有详细描述,包括本章的11.2.1-11.2.8,在此不再赘述,补充一些其中缺少的内容
1.通过mkfs创建虚拟磁盘
在Linux下,可以通过指令
mkd2fs [-b blksize -N ninodes] device nblocks
创建一个带有nblocks个块和ninodes个索引节点的EXT2文件系统
11.3 邮差算法
这一部分的邮差算法,以我个人的理解就是将一个二维存在的数据转变为线性的记录,以书中的例子进行举例,每个房子都同时具有街区与房子两个编号BA =(街区,房子),而邮差算法就是要将其转变为线性地址LA。
1.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语言结构体。
2.将索引节点号转换为磁盘上的索引节点
在 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。
11.4 文件系统的实现
图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指向挂载点的内存索引节点。后面将会讲到,这些双链接指针允许我们在遍历文件系统树时跨越挂载点。此外,挂载表条目还可能包含挂载文件系统的其他信息,例如超级块、块组描述符、位图和索引节点启动块的值,以便快速访问。如果任何缓存项有修改,当卸载设备时,必须将它们写回设备。
11.5 文件系统的级别
文件系统的实现分为三个级别。每个级别处理文件系统的不同部分。这使得实现过程模块化,更容易理解。在文件系统的实现过程中,FS目录包含实现 EXT2 文件系统的文件。文件结构如下。
第1级别实现了基本文件系统树,包含以下文件,实现了指定函数。
使用第1级别FS函数的用户命令程序有:
mkdir,creat,mkond,rmdir,link,symlink,rm,ls,cd和pwd等
第2级别实现了文件内容的读/写函数。
第3级别实现了文件系统的挂载、卸载和文件保护。
11.6 基本文件系统
1.type.h文件
这类文件包含 EXT2文件系统的数据结构类型,比如超块、组描述符、索引节点和目录条目结构。此外,它还包含打开文件表、挂载表、PROC结构体和文件系统常数。
2.global.c文件
这类文件包含文件系统的全局变量
11.7 实践
由于实践内容过多,选取其中一小部分进行练习。
1.创建虚拟磁盘
2.使用df命令查看目前在 Linux 系统上的文件系统磁盘使用情况统计。
3.du命令,显示文件或目录所占用的磁盘空间。
[-sh]显示当前目录的大小:
[-sh vdisk]显示vdisk所占大小
[-sh /.*]显示当前目录下所有文件大小
问题:df命令与du命令的区别是什么?
du[disk usage]命令:
是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在的,没有被删除的。他计算的大小就是当前他认为存在的所有文件大小的累加和。
df[disk free]命令:
通过文件系统来快速获取空间大小的信息,当我们删除一个文件的时候,这个文件不是马上就在文件系统当中消失了,而是暂时消失了,当所有程序都不用时,才会根据OS的规则释放掉已经删除的文件, df记录的是通过文件系统获取到的文件的大小,他比du强的地方就是能够看到已经删除的文件,而且计算大小的时候,把这一部分的空间也加上了,更精确了。