Skip to content

入门:文件抽象、目录与路径

基于通用操作系统概念 · 核于 2026-08

速查

  • 文件(File):磁盘上一组相关数据的命名集合——文件系统把无序的磁盘块包装成有名字、可读写、可保护的逻辑单元,是"长期存储信息"的最小抽象(关机不丢)。
  • 文件 = 数据 + 属性:数据是字节流(UNIX 哲学"一切皆文件",二进制/文本一视同仁);属性/元数据包括名称、类型、大小、位置、创建/修改时间、属主、权限位(rwx)、inode 号等。
  • 文件类型:UNIX 用首字节魔数(magic number,如 ELF/脚本 #!)识别,不靠扩展名;Windows 则重度依赖扩展名(.exe/.txt/.jpg)决定打开程序。
  • 目录(Directory/Folder):特殊的文件,内容是一组目录项(目录项),每项映射文件名 → inode/位置。目录把命名空间组织成层次,便于分类与查找。
  • 目录结构演进:单级(全部文件同一目录,早期 CP/M)→ 树形(UNIX/Linux/Windows 主流,根 / 下层层嵌套)→ 无环图(允许一个文件多个路径,软/硬链接)。
  • 绝对路径:从根目录 / 起算的完整路径(如 /home/alice/a.txt),与当前目录无关,唯一确定。
  • 相对路径:从当前工作目录(cwd)起算(如 ../bob/b.txt),依赖当前所在目录,简短但易变。
  • 特殊目录名. = 当前目录,.. = 上一级目录,~ = 用户家目录(shell 约定,非 OS 语义)。
  • 文件操作(系统调用)create/open(打开,返回 fd)/read/write/lseek(定位,随机访问)/close/unlink(删除硬链接)/truncate/rename——本质是对目录项 + inode 的增删改查。
  • 访问方式顺序访问(磁带模型,从头到尾读,最常见)、随机/直接访问(按偏移 lseek 定位,数据库/索引依赖)、索引访问(按键查,需 FS/DB 支持如 B+ 树)。
  • 文件系统职责命名(路径树)、分配(数据存哪些块)、空闲管理(哪些块可用)、目录管理(名→位置映射)、保护(权限)、一致性(断电不损坏)。
  • 挂载(mount):把一个文件系统的根接到主文件系统树的某个目录(挂载点),形成统一的命名空间——Linux 的"单一全局树"由挂载拼装而成。
  • 进阶顺序文件分配与索引(数据怎么存 + inode)→ 目录结构与链接(软硬链接 + 空闲管理)→ 参考

一、文件抽象:从磁盘块到命名文件

磁盘的物理接口极其朴素——按扇区(sector,通常 512B)/块(block,通常 4KB)读写。如果让用户直接操作"读第 12345 号块",系统几乎无法使用。文件系统的核心抽象是文件:把一个逻辑文件的内容映射到若干物理块上,并提供名字供人引用。

        用户/程序视角                    文件系统内部
   ┌─────────────────┐            ┌──────────────────────┐
   │  a.txt  3.2KB   │  ──映射──▶ │  inode #1234         │
   │  (命名 + 字节) │            │   指针 → 块 200      │
   └─────────────────┘            │   指针 → 块 201      │
                                  │   (2 个 4KB 块)     │
                                  └──────────────────────┘
  • 一切皆文件(UNIX 哲学):普通文件、目录、设备(/dev/sda)、管道(/dev/fd)、套接字都用统一的 open/read/write 接口,降低心智负担。
  • 文件 = 数据 + 属性:数据是字节流;属性(元数据)由文件系统单独存储(inode 中)。ls -l 看到的权限、属主、大小、时间全是属性。

二、文件属性与类型

属性(元数据) 是文件"除了内容之外的信息",存储在 inode 或目录项中:

属性说明查看
名称文件名(存在目录项,非 inode)ls
类型普通/目录/链接/设备/管道ls -l 首字符
大小字节数ls -l
时间atime/mtime/ctimestat
属主/组owner/groupls -l
权限rwx(属主/组/其他)ls -l
inode 号索引节点号ls -i
数据块位置指针(存在 inode)debugfs

文件类型的识别有两种风格:

  • UNIX/Linux:魔数——读文件首字节判断(ELF 可执行、#! 脚本、PK zip 压缩)。扩展名只是约定,mv a.txt a 仍可执行。
  • Windows:扩展名——.exe/.txt/.jpg 决定关联程序。改扩展名可能改变打开方式,安全性较差(病毒靠改后缀伪装)。

特殊文件类型:目录(内容是目录项)、符号链接(内容是目标路径)、设备文件(字符设备/块设备,对应外设)、管道/套接字(用于通信)。

三、目录:命名空间与目录项

目录本身也是文件,但其数据是一张文件名 → inode的映射表,每一行叫目录项(directory entry,dentry)

   目录 /home/alice 的内容(目录项表)
   ┌──────────────┬──────────┬────────────────┐
   │ 文件名       │ inode 号 │ 其他(类型)   │
   ├──────────────┼──────────┼────────────────┤
   │ a.txt        │ 1234     │ 普通文件       │
   │ photos       │ 5678     │ 目录           │
   │ proj → ../p  │ 9012     │ 符号链接       │
   └──────────────┴──────────┴────────────────┘
  • 文件名与 inode 分离:文件名在目录项里,inode 存属性与块指针——这是硬链接存在的基础(多个文件名指向同一 inode)。
  • 硬链接计数(link count):inode 中记录有多少目录项指向它,删到 0 才真正释放数据块。

目录结构的演进:

结构说明问题
单级所有文件在同一目录文件一多就乱,无法分类(早期 CP/M)
树形/ 下层层嵌套,每个文件唯一路径主流,但一个文件不能有多个路径
无环图允许子目录被共享(软/硬链接)需防环(软链接可成环,要小心)

四、路径:绝对与相对

路径(path) 是定位文件的字符串,由 / 分隔的目录名序列组成:

  • 绝对路径:从根 / 起算,如 /home/alice/a.txt唯一、与当前目录无关,适合配置文件、脚本引用。
  • 相对路径:从当前工作目录(cwd,pwd 显示)起算,如 photos/a.jpg../bob/b.txt。简短但随 cwd 变化。
  • .... 是当前目录(常用于 ./run.sh 强制执行本目录文件),.. 是上一级目录(cd .. 返回上层)。
  • 路径分隔符:UNIX 用 /,Windows 用 \(但现代 Windows API 也接受 /)。
  • 大小写:UNIX/Linux 区分大小写(A.txta.txt),Windows/​macOS(默认 HFS+/APFS)大小写不敏感。

解析路径时,文件系统逐级查目录项/home/alice/a.txt → 读根目录找 home 的 inode → 读 home 目录找 alice → 读 alice 目录找 a.txt 的 inode → 读数据块。每经过一层目录都要一次查找,所以目录层级太深会影响路径解析速度(VFS 的 dentry 缓存能缓解)。

五、文件访问方式

访问方式说明典型场景
顺序访问从头到尾依次读写,最简单文本流、日志、音视频流
随机/直接访问lseek 到任意偏移再读写数据库、索引(需分配方式支持)
索引访问按键查记录(B+ 树)数据库(需 FS 或上层支持)

随机访问是否高效取决于分配方式:连续分配最佳(直接算偏移),索引分配(inode)也支持(按间接指针定位),链接分配不支持(要顺着链表走)。这解释了为什么数据库文件必须放在支持随机访问的 FS 上。

下一步

理解了文件抽象与目录、路径后,下一步深入数据怎么存——文件分配与索引(连续/链接/索引分配的取舍、inode 的多级间接指针、随机访问的支持)。