第十届遥感技术与应用国际会议(ICRSTA 2026)
2026/1/16 18:05:33
文件描述符是操作系统为进程管理打开文件/资源分配的整数句柄。它是Unix/Linux系统中所有I/O操作的核心抽象。
0- stdin(标准输入)1- stdout(标准输出)2- stderr(标准错误)进程A 内核 ├── 文件描述符表 ├── 系统级打开文件表 │ fd 0 → 条目1 │ 条目1 → 文件信息1 │ fd 1 → 条目2 │ 条目2 → 文件信息2 │ fd 4 → 条目3 │ 条目3 → 文件信息3 └── └──// 打开文件时获取文件描述符intfd=open("file.txt",O_RDONLY);// fd 可能是 3(如果 0,1,2 已被占用)// 通过 fd 进行读写read(fd,buffer,size);write(fd,buffer,size);// 完成后关闭close(fd);不仅仅是文件!可以是任何I/O资源:
| 资源类型 | 例子 | 如何创建 |
|---|---|---|
| 普通文件 | /etc/passwd | open() |
| 目录 | /home/user | opendir() |
| 网络套接字 | TCP/UDP连接 | socket() |
| 管道 | 进程间通信 | pipe() |
| 设备文件 | /dev/tty,/dev/null | open() |
| 符号链接 | 软链接文件 | open() |
# 查看当前shell的文件描述符ls-la /proc/$$/fd# 输出示例:# lrwx------ 1 user user 64 Dec 10 10:00 0 -> /dev/pts/0# lrwx------ 1 user user 64 Dec 10 10:00 1 -> /dev/pts/0# lrwx------ 1 user user 64 Dec 10 10:00 2 -> /dev/pts/0# lr-x------ 1 user user 64 Dec 10 10:00 3 -> /etc/passwd# 使用 lsof 查看lsof-p<PID># 使用 /procls-la /proc/<PID>/fd/cat/proc/<PID>/fdinfo/3# 查看 fd 3 的详细信息# 子进程继承父进程的文件描述符# 这就是为什么重定向能在管道中工作:ls-l|greptxt2>errors.log# grep 继承了 ls 的 stdout 和 stderr// 多个描述符可以指向同一个文件intfd1=open("file.txt",O_RDONLY);// refcount = 1intfd2=dup(fd1);// refcount = 2close(fd1);// refcount = 1close(fd2);// refcount = 0 → 文件真正关闭进程A 进程B fd3 ----\-->系统打开文件表条目1 -->实际文件 fd2 ----/# 将 stdout (fd 1) 重定向到文件exec1>output.logecho"这会写入文件"# 将 stderr (fd 2) 重定向到 stdoutcommand2>&1# 创建自定义文件描述符exec3<>/tmp/socket# 打开 fd 3 用于读写echo"data">&3# 写入 fd 3readline<&3# 从 fd 3 读取// socket() 返回的也是一个文件描述符!intsock_fd=socket(AF_INET,SOCK_STREAM,0);connect(sock_fd,...);// 使用 fd 连接send(sock_fd,data,...);// 使用 fd 发送recv(sock_fd,buffer,...);// 使用 fd 接收intpipe_fd[2];pipe(pipe_fd);// pipe_fd[0] 用于读,pipe_fd[1] 用于写if(fork()==0){// 子进程:关闭读端,写入数据close(pipe_fd[0]);write(pipe_fd[1],"Hello",6);}# 查看单个进程最大文件描述符数ulimit-n# 查看系统全局限制cat/proc/sys/fs/file-max# 查看当前已使用的文件描述符数cat/proc/sys/fs/file-nr# 输出:已分配 已使用 最大值# 临时修改ulimit-n65536# 永久修改(系统级)echo"fs.file-max = 1000000">>/etc/sysctl.conf sysctl -p# 用户级限制# 编辑 /etc/security/limits.conf# * soft nofile 65536# * hard nofile 65536# 原因:文件描述符耗尽# 查看某个进程打开的文件数ls/proc/<PID>/fd|wc-l# 解决方案:# 1. 增加系统限制# 2. 检查程序是否有文件泄露(未关闭)# 使用 lsof 监控watch-n1'lsof -p <PID> | wc -l'# 使用 /proc 监控watch-n1'ls /proc/<PID>/fd | wc -l'文件描述符的核心价值:
read()、write()、close()几个系统调用正是因为文件描述符的存在,Unix/Linux 才能实现"一切皆文件"的哲学,让复杂的I/O操作变得简单统一。