文件系统 · 操作系统
文件系统怎么把一个路径变成磁盘上的字节?
课程目录为什么需要它
磁盘只会存编号的块。文件系统在上面加了名字、文件夹、大小和权限。弄懂它是怎么做的(inode、块、目录项),就能解释为什么磁盘还有空间却显示「满了」、硬链接是怎么回事、为什么删掉一个正在被写的日志空间不会释放,以及 ls -l 的数字从哪来。
直觉理解
- 块是磁盘上一段固定大小的空间(通常 4 KB)。
- inode 描述一个文件:大小、所有者、权限,以及存放数据的块的列表。它有编号,没有名字。
- 目录是一种特殊文件,把名字映射到 inode 编号。
所以打开 /home/ada/notes.txt 的过程是:在根目录里找 home → inode → 那个目录的条目 → ada → …… → notes.txt → inode → 数据块。
两个名字指向同一个 inode,就是硬链接。只有当没有任何名字、也没有任何打开的程序再引用这个 inode 时,数据才会被释放。
定义
inode 索引节点
A record describing one file (size, owner, mode, timestamps, block list). Directories map names to inode numbers.描述一个文件的记录(大小、所有者、权限、时间戳、块列表)。目录把名字映射到 inode 编号。
块 Block
The unit the disk is divided into. A file uses whole blocks, so a 1-byte file still takes one block.磁盘划分的单位。文件占用整数个块,所以 1 字节的文件也要占一个块。
示例
解析一个路径
动手试试一个迷你文件系统:目录把名字映射到 inode 编号;inode 保存数据。
inodes = {
1: {"type": "dir", "entries": {"home": 2, "etc": 5}},
2: {"type": "dir", "entries": {"ada": 3}},
3: {"type": "dir", "entries": {"notes.txt": 4}},
4: {"type": "file", "data": "buy milk"},
5: {"type": "dir", "entries": {}},
}
def lookup(path):
ino = 1
for name in path.strip("/").split("/"):
node = inodes[ino]
if node["type"] != "dir" or name not in node["entries"]:
return None
ino = node["entries"][name]
return ino
print(lookup("/home/ada/notes.txt"))
print(inodes[lookup("/home/ada/notes.txt")]["data"])
print(lookup("/etc/passwd"))逐步执行
- L10从根目录开始,inode 1。
- L15每个名字通向下一个 inode。
- L18home → 2,ada → 3,notes.txt → 4。
4 - L20/etc 里没有这一项。
None
常见错误
删除仍在被写入的日志
rm 删的只是名字,正在写它的程序还握着这个 inode,所以在它关闭文件或重启之前,空间不会释放。
inode 用光了
几百万个小文件可能把 inode 用光,而块还有剩余:明明显示有空间,却报「No space left on device」。用 df -i 检查。
小测验
1. 这段代码会输出什么?
import math
BLOCK = 4096
for size in [1, 4096, 4097, 10000]:
print(size, math.ceil(size / BLOCK))查看答案
答案:A
文件总是占用整数个块:向上取整。
2. `notes.txt` 和 `copy.txt` 是指向同一个 inode 的硬链接。你 `rm notes.txt`。数据会怎样?
查看答案
答案:A
inode 有一个链接计数。只有降到零时,数据才会被释放。
动手练习
3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。
- 预测输出链接计数
准确写出这段程序的输出。
- 改需求按整块计算
disk_usage(sizes, block)应该返回一组文件实际占用的磁盘字节数。它把文件大小直接相加,但每个文件都占用整数个块。修好它。 - 从零写列出一个目录
用和例子一样的结构,写函数
ls(inodes, path),返回path这个目录里的名字(排好序)。"/"表示根目录,inode 1。路径不存在或不是目录时返回None。
本课术语
| 术语 | 中文 | 英文定义 |
|---|---|---|
| File system | 文件系统 | The layer that turns disk blocks into named files and folders. |
| Inode | 索引节点 | The record describing one file: size, owner, mode and blocks. |
| Hard link | 硬链接 | Another name for the same inode. |