《Linux 文件描述符(File Descriptor)理解》

《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 典型应用

  1. 排查句柄泄漏:监控 /proc/<pid>/fd 数量是否无限增长。
  2. 日志重定向本质就操作 FD:2>&1 是把 stderr(2) 重定向到 stdout(1)。
  3. ulimit -n 调整进程最大 FD 数,解决「too many open files」。
阅读 — · 全站 —
🎸 我的歌单 0 首