目录即文件-Ext文件系统收尾篇

目录即文件:Ext 文件系统的最后一块拼图(附 cd 命令的实现原理)

我的github:(https://github.com/xcx55/ubuntu-linux-project)

感谢各位大佬参观我的github!!

这是 Ext 系列笔记的收尾篇。前面几篇把磁盘硬件、块、分区、inode、位图、路径缓存都过了一遍,

剩下的最后一个疙瘩是:目录,到底是不是文件? 以及我们天天敲的 cd ..,内核到底做了什么?


一、目录就是文件,只是「解读方式」不同

先给出结论,然后逐条验证:

文件和目录,在磁盘和文件系统的视角下完全平等。它们都是「文件项」,都由 inode(属性)+ data blocks(数据)构成。

数据块里存什么,才是二者唯一的分野:

普通文件 目录
inode 属性(权限、大小、时间...) 属性(多一个「我是目录」的标志位)
data blocks 内容 文件正文 「文件名 → inode number」映射表
谁负责解读 文件系统 + 应用 内核(系统调用层用 if/else 分流)

那我们在 ls 时看到的「目录带颜色、带 / 尾缀」是怎么回事?

  • 颜色和 / 是 shell 为了人眼友好故意打印的,不是磁盘上的事实;
  • 内核判断「这是目录」靠的是 inode 里的标志位,而不是内容长相。

换句话说:「是不是目录」这个身份,是从 inode 读出来的;「目录里有什么」,是从数据块里读出来的。 前者是属性,后者是映射关系。


二、路径背后站着的,是那棵 dentry 树

前面我们讲过:路径解析的产物是 struct dentry 组成的全局多叉树(外加 hash 加速)。

所以「路径」这个东西,本质上只是给用户看的一串字符串,它背后真正的对应物是:

复制代码
"/home/user/a.txt"  ──解析──▶  dentry 树上的一个节点  ──▶  struct inode(+inode number)

而 PCB 里的 pwd 指针,就是这棵树上的一个「当前位置坐标」 (注意区分:shell 里的 PWD 只是个字符串环境变量,内核的 pwd 是指针)。


三、cd .. 的一瞬间,内核做了哪些事

把一个命令拆开看,逻辑非常清爽:

  1. shell 解析命令行参数 ,识别出 cd 和参数 ..;
  2. 因为 .. 是父目录这一硬链接的映射 ,内核到当前目录 inode 的数据块里,查「.. 对应的 inode number」;
  3. 顺着该 inode number 拿到父目录 inode(可能触发一次磁盘 IO,构建/命中 dentry 缓存);
  4. 在 dentry 多叉树中移动位置,修改 PCB 的 pwd 指针,指向父目录的 dentry;
  5. shell 把新目录的字符串结果写进 1 号文件(stdout),于是你在屏幕上看到提示符变了。

cd .、cd -、cd /abs/path 同理,只是走的树路径不同。所谓「切换目录」,就是换个指针指向,加一次 stdout 写入------没有复制、没有搬移数据。


四、顺带说清:指令从哪来,参数又从哪来

这一条经常把人绕晕,其实是两条独立的路:

  • 命令本身 :shell 拿着你敲的命令名,去 PATH 环境变量列出的目录里逐个查找可执行文件;
  • 命令要用到的文件和参数 :它不走 PATH ,直接用自己进程 PCB 里继承来的 pwd 指针(以及相对路径解析)就能定位。

这也是为什么 ./a.out 与 a.out 行为不同:

  • a.out → 去 PATH 里的目录找(当前目录通常不在 PATH 里,所以常报 command not found);
  • ./a.out → 明确以「当前工作目录」为起点解析,也就是显式使用那个 pwd 指针。

这就是 . 存在的意义:把「当前目录」和「PATH 搜索」彻底分开。


五、Ext 系列小结

层次 核心结论
硬件 磁盘是黑盒,只认 LBA;机械访问慢,要少碰
抽象 扇区 → 块(4KB)→ 块号即「文件系统的指针」
组织 分区 → 块组 → Super Block / GDT / 双位图 / Inode Table / Data Blocks
索引 文件 = inode(属性)+ Data Blocks(内容),靠 i_block[] 关联,大文件用多级间接
命名 目录 = 「名字 → inode number」映射表;硬链接复用 inode,软链接存路径
加速 dentry 多叉树 + hash 路径缓存,一切性能优化都是空间换时间
统一 目录与文件同构,路径机制先于分区机制,挂载把文件系统接进目录树

到这里,从磁头下的一块扇区 到你敲下 cd .. 时指针的一次移动,整条链路就闭合了。


本文基于 2026-07-18 的学习笔记整理。下一篇进入「库文件」系列:从 .o 到静态库、动态库,再到 ELF 与进程地址空间。

相关推荐
别动我齐刘海7 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
玖石书9 小时前
Ubuntu 24.04 UFW 全命令攻略:从入门到端口开放实战
linux·运维·ubuntu
xiaoqiMikko9 小时前
Linux 实战(七):useradd、sudoers、umask、SGID、软链 —— 三台真机实测
linux·centos
Navigator_Z11 小时前
LeetCode //C - 1288. Remove Covered Intervals
c语言·算法·leetcode
拂拉氏11 小时前
【知识讲解】 Linux之动静态库的了解
linux·运维·服务器·动静态库
Fcy64811 小时前
Linux下 五种IO模型的认识与⾮阻塞IO的实现
linux·服务器·io
Mikko712 小时前
Linux 重启后日志没了?进程被 OOM 杀了去哪看?logrotate 之后日志还往旧文件写?三台真机实测日志与性能排查
linux·运维·centos
书生执笔画浮沉12 小时前
分享一个开源小工具CAdapt
linux·c·gnu·glibc·kernel·升级·灵感
铅笔小新z12 小时前
【C语言】深入理解指针
c语言·开发语言
mounter62512 小时前
Linux 内核热升级(Live Update)技术详解:PCI、VFIO 与 IOMMU 子系统的演进与实战解析引言
linux·linux kernel·kernel·iommu·vfio