在 Linux 和 Unix 系统中,文件描述符(File Descriptor,FD) 是进程用于访问文件、管道、套接字、设备等的一种抽象标识符。本质上,它是一个非负整数,用于标识进程打开的文件或 I/O 资源。
1. 什么是文件描述符?

文件描述符 | 名称 | 作用 | 默认设备 |
---|---|---|---|
0 |
标准输入(stdin) | 读取输入数据 | 键盘 |
1 |
标准输出(stdout) | 输出正常信息 | 终端 |
2 |
标准错误(stderr) | 输出错误信息 | 终端 |
2. 文件描述符的生命周期
一个文件描述符的生命周期包括:
- 分配:进程使用
open()
、socket()
、pipe()
等系统调用打开文件或资源,系统返回一个文件描述符。 - 使用:进程通过
read()
、write()
、send()
、recv()
等操作读写文件描述符指向的资源。 - 关闭:进程调用
close(fd)
释放文件描述符,防止资源泄漏。
3. 文件描述符的创建
(1) open()
打开文件
#include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd = open("test.txt", O_RDONLY); // 以只读模式打开文件 if (fd == -1) { perror("open failed"); return 1; } printf("File Descriptor: %d\n", fd); close(fd); return 0; }
open()
返回的fd
是进程打开的文件描述符。close(fd)
关闭文件,释放描述符。
(2) dup()
和 dup2()
复制文件描述符
dup(fd)
:复制文件描述符,返回新的 FD,指向相同的文件。dup2(old_fd, new_fd)
:将new_fd
复制为old_fd
的副本。
#include <unistd.h> #include <fcntl.h> #include <stdio.h> int main() { int fd = open("test.txt", O_RDONLY); int new_fd = dup(fd); // 复制文件描述符 printf("Original FD: %d, New FD: %d\n", fd, new_fd); close(fd); close(new_fd); return 0; }
4. 文件描述符的使用
4.1) 标准输入/输出重定向
">"
标准输出重定向
echo "Hello World" > output.txt
">"
使 stdout
(文件描述符 1
)指向 output.txt
,不会输出到终端。
"<"
标准输入重定向
wc -l < input.txt
"<"
让 stdin
(文件描述符 0
)从 input.txt
读取,而不是键盘输入。
2>
标准错误重定向
ls non_existing_file 2> error.log
2>
让 stderr
(文件描述符 2
)写入 error.log
,不会输出到终端。
&>
同时重定向 stdout
和 stderr
command &> output.log
&>
让 stdout
和 stderr
都写入 output.log
。
4.2) pipe()
创建管道
#include <unistd.h> #include <stdio.h> int main() { int fd[2]; // fd[0] 读端, fd[1] 写端 pipe(fd); if (fork() == 0) { close(fd[0]); // 子进程关闭读端 write(fd[1], "Hello", 5); close(fd[1]); } else { close(fd[1]); // 父进程关闭写端 char buffer[10]; read(fd[0], buffer, 5); buffer[5] = '\0'; printf("Received: %s\n", buffer); close(fd[0]); } return 0; }
pipe(fd)
创建管道,返回fd[0]
(读端)和fd[1]
(写端)。- 进程通过
read(fd[0])
读取数据,write(fd[1])
发送数据。
5. 文件描述符的查看
5.1) ls -l /proc/<PID>/fd/
ls -l /proc/$(pgrep bash)/fd/
查看进程的所有文件描述符。
5.2) lsof
查看进程打开的文件
lsof -p $(pgrep bash)
列出 bash
进程打开的所有文件。
5.3)fuser
查看占用文件的进程
fuser test.txt
列出访问 test.txt
的所有进程。
6. 文件描述符的限制
6.1) 查看系统允许的最大文件描述符
ulimit -n # 查看单个进程最大文件描述符数 cat /proc/sys/fs/file-max # 查看系统级最大文件描述符数
6.2) 临时修改文件描述符限制
ulimit -n 100000
6.3) 永久修改文件描述符限制
6.3.1) 修改 /etc/security/limits.conf
echo "* soft nofile 100000" >> /etc/security/limits.conf echo "* hard nofile 200000" >> /etc/security/limits.conf
6.3.2) 修改 /etc/pam.d/common-session
wer
除教程外,本网站大部分文章来自互联网,如果有内容冒犯到你,请联系我们删除!