文件系统
问题
Linux 文件系统的核心概念?inode 是什么?文件描述符是什么?
答案
Linux 文件系统层次
用户程序
↓ (系统调用: open/read/write)
VFS (虚拟文件系统)
↓
具体文件系统 (ext4, XFS, tmpfs...)
↓
块设备驱动
↓
磁盘
inode 与 block
| 概念 | 说明 |
|---|---|
| inode | 存储文件的元数据(权限、大小、时间、数据块位置),不存文件名 |
| block | 存储文件的实际数据内容 |
| 目录 | 特殊文件,内容是「文件名 → inode 号」的映射表 |
# 查看文件 inode 信息
ls -i file.txt # 显示 inode 号
stat file.txt # 详细 inode 信息
df -i # 查看 inode 使用情况
文件描述符(fd)
进程打开文件时,内核返回一个整数(文件描述符),后续通过 fd 操作文件。
| fd | 含义 |
|---|---|
| 0 | 标准输入(stdin) |
| 1 | 标准输出(stdout) |
| 2 | 标准错误(stderr) |
| 3+ | 自定义打开的文件/Socket |
# 查看进程打开的文件描述符
ls -la /proc/<pid>/fd
# 查看系统 fd 限制
ulimit -n # 通常默认 1024
fd 与高并发
每个 Socket 连接需要一个 fd。高并发服务器需要调整 ulimit -n 和 /etc/security/limits.conf,否则 fd 耗尽会报 "Too many open files"。
硬链接 vs 软链接
| 维度 | 硬链接 | 软链接(符号链接) |
|---|---|---|
| 本质 | 同一个 inode 的不同文件名 | 独立文件,内容是目标路径 |
| 跨分区 | ❌ | ✅ |
| 链接目录 | ❌ | ✅ |
| 删除原文件 | 不影响(inode 引用计数 > 0) | 链接失效 |
常见面试问题
Q1: 为什么 Java 需要关注文件描述符?
答案:
Java 中每个 Socket 连接、文件流、数据库连接都对应一个 fd。如果不及时关闭(未在 finally/try-with-resources 中关闭),会导致 fd 泄漏。当 fd 达到系统限制时,新连接会失败。
Netty 和 Tomcat 等服务器在启动时通常会检查并建议调整 ulimit -n。
Q2: 删除一个正在被进程使用的文件会怎样?
答案:
Linux 上 rm 只是删除了目录中的文件名 → inode 映射。如果该文件还被进程打开(引用计数 > 0),实际磁盘空间不会释放。直到进程关闭该文件后,inode 引用计数归零,空间才真正释放。
这就是为什么删除了大日志文件但磁盘空间没释放——因为进程还在写它。需要重启进程或 truncate 文件。