软考(软件设计师)存储管理—存储空间管理,文件共享保护
一、文件存取方法
1. 顺序存取(Sequential Access)
- 原理:按记录写入顺序依次访问
- 特点:
- 读操作:读取当前位置,指针自动前移
- 写操作:追加到文件末尾
- 适用场景:磁带设备、日志文件
2. 直接存取(Direct Access / Random Access)
- 原理:直接定位到任意位置读写
- 操作方式:
seek(offset)
移动文件指针read(size)
/write(data)
在当前位置操作
- 磁盘支持:通过计算物理地址实现
3. 索引存取(Indexed Access)
- 原理:通过索引表查找记录位置
- 工作流程:
- 搜索索引找到记录键
- 获取记录物理地址
- 直接访问该地址
二、存储空间管理技术
1. 空闲空间管理方法
2. 位示图法(Bitmap)
位示图法是一种用二进制位管理磁盘空间的技术,其基本原理如下:
- 数据结构:创建一个位数组(bit array),数组长度等于磁盘总块数
- 映射关系:
- 每个二进制位对应一个磁盘块
0
表示空闲块1
表示已分配块
- 存储位置:位示图通常存储在磁盘固定位置(如超级块附近)
完整示例:16块磁盘的位示图管理
初始状态(全空闲):
磁盘块号: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
位示图值: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
操作1:分配块2、块5、块7
更新后位示图:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0
操作2:分配3个连续块
更新后位示图:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0
操作3:释放块5和块10
更新后位示图:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0
关键技术细节
1. 地址转换计算
-
块号 → 位位置:
- 字节偏移 = 块号 / 8
- 位偏移 = 块号 % 8
-
示例:访问块13
字节偏移 = 13 / 8 = 1 (第二个字节) 位偏移 = 13 % 8 = 5 检查第2字节的第5位(从0开始计数)
2. 空间占用计算
假设:
- 磁盘容量:1TB
- 块大小:4KB
计算过程:
总块数 = 1TB / 4KB = 2^30 / 2^12 = 2^18 = 262,144 块
位示图大小 = 262,144 bits / 8 = 32,768 bytes = 32KB
位示图法优缺点分析
优点 | 缺点 |
---|---|
✅ 空间效率高:仅需约 0.0039% 的额外空间(1/256) | ❌ 分配连续空间需线性扫描 |
✅ 状态切换快:位操作效率极高 | ❌ 大磁盘中扫描效率低 |
✅ 实现简单:数据结构简洁 | ❌ 外部碎片问题仍然存在 |
✅ 随机访问快:直接计算位置 | ❌ 需要整个位图载入内存 |
3. 空闲链表法
- 物理链表实现:
4. 空闲区表法(Extent-Based)
原理
空闲区表法(Free Space Management with Extent Lists)是一种通过记录连续空闲区域来管理磁盘空间的技术,特别适合处理连续分配的场景。其核心思想是:
- 数据结构:维护一张表格(或链表),每个表项记录:
- 空闲区的起始块号
- 空闲区的长度(连续块数)
- 分配策略:当需要空间时,在表中查找满足需求的空闲区
- 合并机制:释放空间时自动合并相邻空闲区
完整示例:16块磁盘的空闲区表管理
初始状态(全空闲):
操作1:分配3个连续块
更新后空闲表:
空闲区1: 起始块=3, 长度=13
操作2:再分配5个连续块
更新后空闲表:
空闲区1: 起始块=8, 长度=8
操作3:释放块0-2(3块)
更新后空闲表:
空闲区1: 起始块=0, 长度=3
空闲区2: 起始块=8, 长度=8
操作4:释放块3-7(5块)
最终空闲表:
分配策略对比
策略 | 操作方式 | 优点 | 缺点 |
---|---|---|---|
首次适应 | 从表头扫描,选择首个足够大的区域 | 分配速度快 | 易产生外部碎片 |
最佳适应 | 扫描整个表,选择最小的足够区域 | 减少大空闲区割裂 | 易产生微小碎片 |
最差适应 | 扫描整个表,选择最大的空闲区 | 减少微小碎片 | 破坏大空闲区 |
空间占用计算
假设:
- 磁盘容量:1TB
- 块大小:4KB
- 平均空闲区大小:16块
计算:
总块数 = 1TB / 4KB = 256M 块
平均空闲区数 = 256M / 16 = 16M
表项大小 = 8字节(4字节起始块 + 4字节长度)
总空间 = 16M × 8B = 128MB
优缺点分析
优点 | 缺点 |
---|---|
✅ 减少外部碎片 | ❌ 分配时间随表增大而增加 |
✅ 高效管理大文件 | ❌ 小碎片无法利用 |
✅ 支持快速连续访问 | ❌ 需要定期合并操作 |
✅ 实现相对简单 | ❌ 大磁盘中表可能很大 |
5. UNIX成组链接法
成组链接法是UNIX文件系统采用的高效空闲块管理方法,核心思想是:
- 分组管理:将空闲块分成若干组
- 链式连接:每组最后一个块存储下一组信息
- 超级块缓存:内存中缓存第一组空闲块信息
完整示例:12块磁盘的成组链接管理
初始状态(3块/组):
内存超级块内容:
空闲块数 | 空闲块列表 |
---|---|
3 | [1, 2, 3] |
操作1:分配3个块
操作2:再分配1个块
操作3:释放块10,11,12
优缺点分析
优点 | 缺点 |
---|---|
✅ 分配效率高(O(1)平均) | ❌ 实现复杂度高 |
✅ 释放操作快速 | ❌ 小规模磁盘不划算 |
✅ 减少磁盘I/O(超级块缓存) | ❌ 需维护链式结构 |
✅ 天然抵抗碎片化 | ❌ 极端情况需递归加载 |
三、文件共享和保护
文件共享机制
软链接与硬链接
硬链接(Hard Link)
底层原理
在 Linux 文件系统中:
- 每个文件对应一个唯一的 inode(索引节点)
- inode 存储文件的元数据(权限、大小、时间戳等)
- 硬链接是指向同一个 inode 的多个目录项
创建与操作(终端命令)
# 创建原始文件
$ echo "Original Content" > original.txt# 创建硬链接
$ ln original.txt hardlink.txt# 查看inode信息
$ ls -li
123456 -rw-r--r-- 2 user group 17 Jan 1 10:00 hardlink.txt
123456 -rw-r--r-- 2 user group 17 Jan 1 10:00 original.txt
# ↑ 相同的inode号(123456)和链接数(2)# 修改硬链接文件
$ echo "New content" >> hardlink.txt# 检查原始文件
$ cat original.txt
Original Content
New content# 删除原始文件
$ rm original.txt# 硬链接仍然有效
$ cat hardlink.txt
Original Content
New content
关键特性
特性 | 说明 |
---|---|
inode 相同 | 所有硬链接共享同一 inode |
文件大小 | 与原文件相同(不占用额外空间) |
跨文件系统 | ❌ 不支持 |
链接目录 | ❌ 不允许(避免循环引用) |
删除影响 | 减少链接计数,仅当计数为0时删除数据 |
权限同步 | 所有硬链接权限始终相同(同一 inode) |
使用场景
- 文件多重备份(防止误删)
- 同一文件需要在多个位置访问
- 节省空间的"副本"创建
软链接(Symbolic Link / Symlink)
底层原理
- 软链接是独立的文件,有自己的 inode
- 内容存储目标文件的路径(字符串)
- 类似Windows的快捷方式
创建与操作(终端命令)
# 创建原始文件
$ echo "Source Content" > source.txt# 创建软链接(绝对路径)
$ ln -s /home/user/source.txt abs_link.txt# 创建软链接(相对路径)
$ ln -s source.txt rel_link.txt# 查看链接信息
$ ls -l
lrwxrwxrwx 1 user group 11 Jan 1 10:00 abs_link.txt -> /home/user/source.txt
lrwxrwxrwx 1 user group 10 Jan 1 10:00 rel_link.txt -> source.txt
-rw-r--r-- 1 user group 15 Jan 1 10:00 source.txt# 访问软链接
$ cat rel_link.txt
Source Content# 删除原始文件
$ rm source.txt# 软链接失效(断链)
$ cat rel_link.txt
cat: rel_link.txt: No such file or directory# 检查断链状态
$ ls -l rel_link.txt
lrwxrwxrwx 1 user group 10 Jan 1 10:00 rel_link.txt -> source.txt # 红色显示
关键特性
特性 | 说明 |
---|---|
inode | 独立于目标文件 |
文件大小 | 等于路径字符串长度 |
跨文件系统 | ✅ 支持 |
链接目录 | ✅ 允许 |
删除影响 | 目标文件删除后失效 |
权限 | 总是 777(实际权限由目标决定) |
核心区别对比
特性 | 硬链接 | 软链接 |
---|---|---|
本质 | 同一文件的多个目录项 | 存储路径的特殊文件 |
inode | 与目标文件相同 | 独立 inode |
跨文件系统 | ❌ 不支持 | ✅ 支持 |
链接目录 | ❌ 禁止 | ✅ 允许 |
原始文件删除 | 仍可访问(链接数减1) | 链接失效(断链) |
文件大小 | 与目标文件相同 | 路径字符串长度 |
路径依赖 | 无 | 相对路径依赖位置 |
更新影响 | 所有链接同步更新 | 链接指向不变,目标可更换 |
权限 | 与目标相同 | 总是 lrwxrwxrwx |
查找命令 | find . -samefile 文件 | find -type l -ls |
Linux 系统视角
文件保护机制
1. 访问控制矩阵
2. 访问控制列表(ACL)
- 原理:为每个文件维护权限列表
- 结构:
3. UNIX权限模型(9-bit)
权限位分解
“文件类型”: 1
“所有者权限” : 3
“组权限” : 3
“其他用户” : 3
权限示例:
第一位表示文件的类型,-代表文件,d代表目录
-rwxr-xr--↑↑↑↑ ↑↑│||| |└─ 其他:读│||| └── 组:执行│|│└── 组:读││└──── 所有者:执行|└───── 所有者:写└────── 所有者:读
[“hardlink → inodeX”]
Directory2[目录] --> EntryC[“symlink → inodeY”]
#### 文件保护机制##### 1. 访问控制矩阵```mermaid
graph LRA[访问控制矩阵] --> B[域:用户/进程]A --> C[对象:文件]B --> D[权限:R/W/X]
2. 访问控制列表(ACL)
- 原理:为每个文件维护权限列表
- 结构:
3. UNIX权限模型(9-bit)
权限位分解
“文件类型”: 1
“所有者权限” : 3
“组权限” : 3
“其他用户” : 3
权限示例:
第一位表示文件的类型,-代表文件,d代表目录
-rwxr-xr--↑↑↑↑ ↑↑│||| |└─ 其他:读│||| └── 组:执行│|│└── 组:读││└──── 所有者:执行|└───── 所有者:写└────── 所有者:读