文件描述符

什么是文件描述符?

文件描述符(File Descriptor)是内核为了管理已经打开的文件而创建的索引。它是一个非负整数,在形式上表现为一个整数。在Linux系统中,所有对设备的操作、对文件的操作都可以通过文件描述符来进行。

标准文件描述符

Linux系统为每个进程自动打开三个标准文件描述符:

  • 0 - 标准输入(stdin) - 默认连接到键盘

  • 1 - 标准输出(stdout) - 默认连接到终端屏幕

  • 2 - 标准错误(stderr) - 默认连接到终端屏幕

文件描述符的工作原理

当进程打开文件时,内核会:

  1. 在文件描述符表中寻找一个空闲的条目

  2. 为该文件分配一个文件描述符(一个小的非负整数)

  3. 在文件表中创建一个条目,包含文件的访问模式、当前位置等信息

  4. 返回文件描述符给进程

文件描述符的范围

  • 0-2: 保留给标准输入、标准输出和标准错误

  • 3-9: 可用于用户自定义的文件描述符

  • 10及以上: 通常用于程序内部使用

文件描述符与I/O重定向

文件描述符是I/O重定向的基础。通过重定向,我们可以:

  • 将标准输出重定向到文件

  • 将标准错误重定向到文件

  • 将标准输入重定向从文件读取

  • 在文件描述符之间进行复制

示例

# 查看当前进程的文件描述符
$ ls -la /proc/self/fd/

# 创建新的文件描述符
$ exec 3< input.txt    # 打开文件用于读取,文件描述符为3
$ exec 4> output.txt   # 打开文件用于写入,文件描述符为4

# 使用文件描述符
$ cat <&3              # 从文件描述符3读取
$ echo "hello" >&4     # 写入到文件描述符4

# 关闭文件描述符
$ exec 3<&-           # 关闭文件描述符3
$ exec 4>&-           # 关闭文件描述符4

文件描述符的限制

每个进程都有文件描述符数量的限制,可以通过以下命令查看:

# 查看系统限制
$ ulimit -n

# 查看进程当前打开的文件描述符数量
$ ls /proc/<PID>/fd/ | wc -l

系统调用

常用的文件描述符相关系统调用:

  • open() - 打开文件,返回文件描述符

  • close() - 关闭文件描述符

  • read() - 从文件描述符读取

  • write() - 写入到文件描述符

  • dup() - 复制文件描述符

  • fcntl() - 操作文件描述符属性

参考资料

最后更新于