4.1 文件的基本概念
文件系统提供的服务:文件访问(按名存取)、文件创建/删除、目录管理、访问控制、文件共享与保护。
4.2 文件逻辑结构
文件的逻辑结构是用户可见的组织形式,与存储介质无关。
| 类型 | 说明 | 特点 |
|---|---|---|
| 顺序文件 | 记录顺序排列 | 可顺序/随机访问;定长可随机存取 |
| 索引文件 | 建立索引表 | 支持快速随机访问,变长记录适用 |
| 索引顺序文件 | 分组+组内索引 | 顺序与索引结合 |
| 直接文件/散列文件 | 关键字直接映射地址 | 访问快,有冲突 |
4.3 文件目录
目录是文件控制块 (FCB) 的集合,用于实现"按名存取"。FCB 包含文件名、类型、大小、物理位置、创建时间、权限等。
| 目录结构 | 说明 | 优缺点 |
|---|---|---|
| 单级目录 | 所有文件在同一目录 | 简单;不允许重名 |
| 两级目录 | 主文件目录 + 用户文件目录 | 允许重名;不便共享 |
| 多级目录(树形) | 层次结构,含路径 | 层次清晰;不便文件共享 |
| 无环图目录 | 树形 + 共享链接 | 支持共享;需处理循环 |
4.4 文件物理结构
文件的物理结构是指文件在磁盘上的存储组织方式。
| 结构 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| 连续分配 | 文件占用连续磁盘块 | 顺序/随机访问都快 | 外部碎片,文件难扩展 |
| 链接分配(隐式) | 每个盘块含指向下一块的指针 | 无外部碎片,可扩展 | 只能顺序访问,指针占空间 |
| 链接分配(显式/FAT) | 指针集中存于FAT表 | 随机访问快 | FAT 占用内存 |
| 索引分配 | 每个文件一张索引表 | 支持随机访问,无碎片 | 索引表本身占空间 |
混合索引(inode)
UNIX/Linux 的 inode 采用混合索引:直接索引块(小文件直接寻址)+ 一级间接索引 + 二级间接索引 + 三级间接索引。
| 索引级别 | 寻址范围 |
|---|---|
| 直接地址(12 个) | 小文件,直接指向数据块 |
| 一级间接索引 | 中等文件,索引块指向数据块 |
| 二级间接索引 | 大文件,索引块→索引块→数据块 |
| 三级间接索引 | 超大文件,三级间接 |
交互式动画 · inode多级索引寻址
UNIX inode混合索引:12直接块+1一级间接+1二级间接+1三级间接。调节参数计算最大文件大小。
4.4B 虚拟文件系统 VFS [22新增]
VFS 四大对象
VFS 通过四个核心数据结构来描述和管理文件系统:
| 对象 | 数据结构 | 存储位置 | 说明 |
|---|---|---|---|
| 超级块对象 | super_block | 磁盘(特定位置) | 描述已挂载文件系统的整体信息:文件系统类型、块大小、根 inode 号、空闲块数等。每个挂载的文件系统有一个超级块。 |
| 索引节点对象 | inode | 磁盘 | 描述一个文件的所有属性信息(大小、权限、时间戳、指向数据块的指针)。每个文件对应一个 inode。 |
| 目录项对象 | dentry | 内存(缓存) | 描述目录项(文件名→inode 映射)。dentry 缓存 (dcache) 加速路径名查找。每个路径分量对应一个 dentry。 |
| 文件对象 | file | 内存 | 描述一个已打开的文件(打开模式、当前读写位置)。一个文件可被多次打开,每次打开创建一个 file 对象。 |
VFS 支持多种具体文件系统:ext4(Linux 默认)、xfs(高性能日志文件系统)、NTFS(Windows 文件系统)、FAT32(U 盘常用)、NFS(网络文件系统)等。VFS 为每种文件系统定义一组函数指针(如 read_inode、write_inode),具体文件系统实现这些函数即可接入 VFS。
4.4C 文件系统挂载 [22新增]
挂载过程
以 mount /dev/sdb1 /mnt/data 为例,挂载一个 ext4 分区到 /mnt/data 目录:
- ① 读取超级块:内核从 /dev/sdb1 中读取文件系统的超级块(superblock),检查文件系统类型(ext4)、确认文件系统完整性。
- ② 创建 VFS 结构:在内存中创建该文件系统的超级块对象 (super_block)、根目录的 inode 和 dentry,构建 VFS 的内部数据结构。
- ③ 关联到挂载点:将文件系统的根目录 dentry 关联到挂载点 /mnt/data 的 dentry。此后对 /mnt/data 的访问将透明地重定向到 /dev/sdb1 上的文件系统。
- ④ 挂载完成:该文件系统加入全局文件系统链表中,可被正常访问。
卸载 (umount)
卸载是挂载的逆过程:检查文件系统是否仍有打开的文件或正在使用的目录(如有则拒绝卸载)→ 将内存中的脏数据(dirty pages/buffers)同步写回磁盘 → 断开挂载点关联 → 释放 VFS 数据结构(超级块、inode、dentry)。
mount 命令或 /etc/fstab 配置文件实现自动挂载。4.5 磁盘存储管理
磁盘是文件的存储介质。磁盘访问时间 = 寻道时间 + 旋转延迟 + 传输时间。其中寻道时间是主要开销,磁盘调度算法旨在减少平均寻道时间。
交互式动画 · 磁盘访问时间计算器
调节磁盘参数(RPM、寻道距离、数据量等),实时计算寻道时间、旋转延迟、传输时间及总时间。
磁盘调度算法
- FCFS 先来先服务:按请求到达顺序服务。公平,但寻道距离大。
- SSTF 最短寻道时间优先:选择离当前磁头最近的请求。性能好,但远处请求可能饥饿。
- SCAN 电梯调度:磁头沿一个方向移动到磁盘端点,途中服务所有请求,到达端点后反向。各方向请求均匀服务。
- C-SCAN 循环扫描:磁头单向移动到端点后直接返回另一端(不服务返回途中的请求),提供更均匀的等待时间。
- LOOK / C-LOOK:SCAN/C-SCAN 的改进,磁头只移动到最远请求位置而非磁盘物理端点。
磁盘调度算法伪代码
// FCFS 先来先服务
void FCFS(queue requests, int head){
int totalSeek = 0;
for(each r in requests){
totalSeek += abs(r - head);
head = r;
}
}
// SSTF 最短寻道时间优先
void SSTF(queue requests, int head){
int totalSeek = 0;
while(requests 非空){
int nearest = argmin(requests, r => abs(r-head));
totalSeek += abs(nearest - head);
requests.erase(nearest);
head = nearest;
}
}
// SCAN 电梯调度(假设向上)
void SCAN(queue requests, int head, int maxCyl){
int totalSeek = 0;
bool up = true;
while(requests 非空){
if(up){
// 向上移动到最远请求或端点
int next = min({r∈requests | r ≥ head});
if(next 为空 || next > maxCyl){ next = maxCyl; up = false; }
totalSeek += abs(next - head);
head = next;
removeAll(requests, r => r == head);
} else {
int next = max({r∈requests | r ≤ head});
if(next 为空){ next = 0; up = true; }
totalSeek += abs(next - head);
head = next;
removeAll(requests, r => r == head);
}
}
}
// C-SCAN 循环扫描(单向)
void CSCAN(queue requests, int head, int maxCyl){
sort(requests);
int totalSeek = 0;
while(requests 非空){
auto it = lower_bound(requests, head);
if(it == requests.end()){ // 到头,单向折返
totalSeek += (maxCyl - head) + maxCyl;
head = 0;
} else {
totalSeek += abs(*it - head);
head = *it;
requests.erase(it);
}
}
}
4.6 文件存储空间管理
磁盘空闲空间管理方法:
- 空闲表法:连续空闲区记录为表项(起始块、长度)。
- 空闲链表法:空闲盘块用链表串联,或空闲区链表。
- 位示图法:每位对应一个盘块,1=已分配,0=空闲。常用,开销小。
- 成组链接法:UNIX 采用,将空闲盘块分组,组间用链接管理。
4.7 文件保护与安全
文件保护指防止文件被非法访问、篡改或破坏,主要实现方式有:
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 访问控制表 ACL | 每个文件关联一个 ACL,记录每个用户/组对该文件的权限(读/写/执行) | 权限精细,可针对单用户设置 | 文件多时 ACL 冗长,管理开销大 |
| Unix rwx 权限位 | 按文件所有者/同组用户/其他用户三类,每类用 r(读)w(写)x(执行) 三位表示 | 结构简单,开销小 | 权限粒度粗,难以表达复杂权限 |
| 口令保护 | 文件设置访问口令,访问时需验证口令 | 实现简单 | 口令易泄露,安全性弱 |
| 密码加密 | 文件内容加密存储,访问时用密钥解密 | 安全性最高,即使被窃取也无法读取 | 加解密开销大,密钥管理复杂 |
Unix rwx 权限位详解
Unix/Linux 文件权限用 9 位二进制(3 组 rwx)表示,常写成八进制。如 rwxr-xr-- = 754:
- 所有者 (owner):rwx = 可读可写可执行
- 同组用户 (group):r-x = 可读可执行,不可写
- 其他用户 (other):r-- = 仅可读