《Linux 文件描述符(File Descriptor)理解》
文件描述符(File Descriptor, FD)是内核给进程提供的一种「访问文件/资源的句柄」,理解它对排查句柄泄漏、日志重定向等非常有用。
1 什么是文件描述符
在 Linux/UNIX 中「一切皆文件」。进程要访问某个文件时,并不会直接操作磁盘 inode,而是请求内核打开文件;内核返回一个整数形式的句柄,即文件描述符 FD。
# 例:tail -f 持续读取文件
sudo tail -f /var/log/messages
# 用 lsof 查看该进程打开的文件,第 4 列即为 FD 号
sudo lsof | grep 'tail '
COMMAND PID USER FD TYPE ...
tail 16724 root 3r REG ... /var/log/messages
2 FD 从 3 开始,因为 0/1/2 被标准流占用
| FD | 标准流 |
|---|---|
| 0 | 标准输入 stdin |
| 1 | 标准输出 stdout |
| 2 | 标准错误 stderr |
任何进程启动时都可访问 0~2,因此新打开的文件 FD 从 3 开始。
3 lsof 中 FD 后面的字母
表示打开模式(参考 lsof man 页 OUTPUT 部分):
| 字母 | 含义 |
|---|---|
| r | 只读 |
| w | 只写 |
| u | 读写 |
| (空) | 模式未知且无锁 |
例如 tail 只需读(3r),syslog 写日志(58w)。
4 FD 在 /proc 下的表现
# 进程的 FD 是符号链接,指向实际文件
sudo ls -l /proc/16724/fd
0 -> /dev/pts/15
1 -> /dev/pts/15
2 -> /dev/pts/15
3 -> /var/log/messages
可以据此判断进程打开了哪些文件。
5 FD 的性质
- 进程私有:FD 对使用它的进程是局部的;同一文件被不同进程打开,对各自进程 FD 号不同。
- 可同时打开多个:一个进程可同时打开很多文件(默认限制一般 1024,可用
ulimit -n调大)。 - 不只文件:FD 也用于目录、socket、管道等,「一切皆文件」。
lsof 输出中的特殊 FD 种类:cwd 当前工作目录、mem 内存映射文件、rtd 根目录、txt 程序正文。例:chroot 环境里的 mysqld,其 rtd 指向 /server/mysql。
6 与 FD 数量的常见坑
「进程打开的文件数量」与「文件描述符数量」并不总是一致:
# 打开的总文件行数
lsof -p <pid> | tail -n +2 | wc -l
# 内核视角的文件描述符数量
ls /proc/<pid>/fd | wc -l
7 典型应用
- 排查句柄泄漏:监控
/proc/<pid>/fd数量是否无限增长。 - 日志重定向本质就操作 FD:
2>&1是把 stderr(2) 重定向到 stdout(1)。 ulimit -n调整进程最大 FD 数,解决「too many open files」。
阅读 —
·
全站 —