一、知识点归纳
(一)知识点整理 第十一章 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文件系统数据结构
磁盘块的内容:
-
Block#0: 引导块
- BO是引导块, 文件系统不会使用它。 它用来容纳一个引导程序, 从磁盘引导操作系统。
-
Block#1: 超级块
- 在硬盘分区中字节偏移量为1024。Bl是超级块, 用于容纳整个文 件系统的信息。
-
Block#2: 块组描述符块
- EXT2 将磁盘块分成几个组。 每个组有 8192 个块(硬盘上的大小为 32K)。每组用一个块组描述符结构体来描述。
-
Block#8: 块位图 (Bmap)
- 位图是用来表示某种项的位序列, 例如磁盘块或索引节点。 位图用于分配和回收项。
-
Block#9: 索引节点位图 (Imap)
- 一个索引节点就是用来代表一个文件的数据结构。 EXT2 文件系统是使用有限数盘的索引节点创建的。各索引节点的状态用 B9 的 Jmap 中的一个位表示。
-
Block#10: 索引(开始)节点
- 每个文件都用一个 128 字节 (EXT4 中 是 256 字节)的唯一索引节点结构体表示。
索引节点结构体中一些内容:
-
i_mode: 为 ul6 或 2 字节无符号整数。
- 在 i_mode 字段中, 前 4 位指定了文件类型, 接下来的 3 位 ugs 表示文件的特殊用法。 最后 9 位是用于文件保护的rwx权限位。
-
i_size: 字段表示文件大小(以字节为单位)。
- 各时间字段表示自 1970 年 1 月 1 日 0 时 0 分0秒以来经过的秒数。借助以下库函数将它们转换为日历形式:
char *ctime(&time_field)
- 各时间字段表示自 1970 年 1 月 1 日 0 时 0 分0秒以来经过的秒数。借助以下库函数将它们转换为日历形式:
-
i_block[15]: 数组包含指向文件磁盘块的指针。
- 直接块: i_block[0] 至 i_block[11], 指向直接磁盘块。
- 间接块: i_block[12] 指向一个包含 256个块编号(对于 1 KB BLKSlZE) 的磁盘块, 每个块编号指向一个磁盘块。
- 双重间接块: i_block[13] 指向一个指向 256 个块的块, 每个块指向 256 个磁盘块。
- 三重间接块: i_block[14] 是三重间接块。 对于 “小型"EXT2 义件系统,可以忽略它。
数据块:
- 文件存储数据块紧跟在索引节点块后面。
-
通过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;
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;
11.4 文件系统的实现
1. 当前运行进程的 PROC 结构体
在实际系统中,每个文件操作都是由当前执行的进程决定的。每个进程都有以下关键属性:
- cwd: 指向进程当前工作目录(CWD)的内存索引节点。
- fd[]: 文件描述符数组,指向打开的文件实例。
2. 文件系统的根指针
文件系统的根指针指向内存中的根索引节点。系统启动时,会选择一个设备作为根设备,该设备必须是有效的 EXT2 文件系统。根设备的根索引节点(inode #2)会加载到内存中作为文件系统的根目录(/),这个操作称为"挂载根文件系统"。
3. openTable 条目
当某个进程打开文件时,进程的 fd 数组的某个条目会指向 openTable,openTable 指向打开文件的内存索引节点。
4. 内存索引节点 (minode)
内存索引节点包含以下关键属性:
dev
和ino
用于确定索引节点的来源,以便将修改后的索引节点写回磁盘。refCount
字段记录使用 minode 的进程数。dirty
字段表示索引节点是否已被修改。- 挂载标志用于指示索引节点是否已被挂载,如果已挂载,
mntabPtr
将指向挂载文件系统的挂载表条目。 lock
字段用于确保内存索引节点一次只能由一个进程访问,例如在修改索引节点时或在读/写操作过程中。
5. 已挂载的文件系统表 (挂载表)
对于每个挂载的文件系统,挂载表中的条目用于记录挂载的文件系统信息,包括挂载的文件系统设备号。挂载点的内存索引节点中,挂载标志会被打开,mntabPtr
指向挂载表条目。挂载表条目还可能包含其他挂载文件系统的信息,例如超级块、块组描述符、位图和索引节点启动块的值,以便快速访问。如果有任何缓存项被修改,当卸载设备时,必须将它们写回设备。
11.5 文件系统的级别
文件系统的实现分为三个级别
基本文件系统
-
type.h: 包含 EXT2 文件系统的数据结构类型,例如超块、组描述符、索引节点和目录条目结构。还包括打开文件表、挂载表、PROC 结构体和文件系统常数。
-
global.c: 包含文件系统的全局变量。
-
util.c: 包含文件系统常用的实用程序函数,其中最重要的实用程序函数包括读/写磁盘块函数
iget()
、iput()
和getino()
。 -
allocate_deallocate.c: 包含关于索引节点和数据块管理的函数。
第1级别文件系统
第1级别实现了基本文件系统树,包括以下文件和指定的函数:
-
mkdir_creat.c: 创建目录和普通文件。
-
ls_cd_pwd.c: 列出目录内容、切换目录和获取当前工作目录路径。
-
rmdir.c: 删除目录。
-
link_unlink.c: 创建硬链接和删除文件。
-
symlink_readlink.c: 创建和读取符号链接文件。
-
stat.c: 返回文件信息。
-
misc1.c: 包含访问权限、chmod、chown、utime 等功能。
用户命令程序使用第1级别文件系统函数,包括 mkdir
、creat
、mknod
、rmdir
、link
、unlink
、symlink
、rm
、ls
、cd
和 pwd
等。
第2级文件系统
第2级文件系统实现了文件内容的读取和写入操作,包括以下函数:
-
open_close_lseek.c: 打开文件以进行读取、写入和追加操作,关闭文件和
lseek
。 -
read.c: 从已打开的普通文件中读取数据。
-
write.c: 写入数据到已打开的普通文件。
-
opendir_readdir.c: 打开和读取目录。
第3级文件系统
第3级文件系统实现了文件系统的挂载、卸载和文件保护,包括以下功能:
-
mount__umount.c: 挂载和卸载文件系统。
-
file_protection: 文件访问权限检查。
-
file-locking: 锁定和解锁文件。
11.6 基本文件系统
1.type.h文件
这类文件包含 EXT2文件系统的数据结构类型,比如超块、组描述符、索引节点和目录条目结构。此外,它还包含打开文件表、挂载表、PROC结构体和文件系统常数。
2.global.c文件
这类文件包含文件系统的全局变量
(二)苏格拉底挑战
1.问题一:
2.问题二:
二、问题与解决思路
(一)出现的问题
df命令与du命令的区别是什么?
du[disk usage]命令:
是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在的,没有被删除的。他计算的大小就是当前他认为存在的所有文件大小的累加和。
df[disk free]命令:
通过文件系统来快速获取空间大小的信息,当我们删除一个文件的时候,这个文件不是马上就在文件系统当中消失了,而是暂时消失了,当所有程序都不用时,才会根据OS的规则释放掉已经删除的文件, df记录的是通过文件系统获取到的文件的大小,他比du强的地方就是能够看到已经删除的文件,而且计算大小的时候,把这一部分的空间也加上了,更精确了。
(二)解决
三、实践过程截图
(一)实践一
1.创建虚拟磁盘
2.使用df命令查看目前在 Linux 系统上的文件系统磁盘使用情况统计。
(二)实践二
1.du命令,显示文件或目录所占用的磁盘空间。
[-sh]显示当前目录的大小:
[-sh vdisk]显示vdisk所占大小
[-sh /.*]显示当前目录下所有文件大小