程序疑似遗留打开文件描述符,如何用lsof查看?
如何查看程序中遗留的打开文件描述符
问题根源
你的程序之所以无法通过常规命令捕获到遗留的文件描述符,核心原因是进程生命周期太短:
- 父进程在
waitpid后直接退出,lsof或/proc文件系统的查询动作赶不上进程存活时间 - 子进程执行
execve调用ls后,ls执行完立刻退出,同样来不及被工具捕获
有效排查方案
方案1:修改代码延长进程存活时间
在父进程和子进程中添加暂停逻辑,给查询留出足够时间,修改后的代码如下:
#include <unistd.h> #include <sys/wait.h> #include <stdio.h> int main() { int my_fd = dup(STDOUT_FILENO); char *cmd[2]; cmd[0] = "/bin/ls"; cmd[1] = NULL; dprintf(2, "pid = %d\n", getpid()); if (fork() != 0) { // 父进程暂停,等待用户输入后继续 printf("Parent paused, press enter to exit...\n"); getchar(); // close(my_fd); waitpid(-1, NULL, WUNTRACED); } else { dup2(my_fd, STDERR_FILENO); // close(my_fd); // 子进程exec前暂停 printf("Child paused, press enter to run ls...\n"); getchar(); execve(cmd[0], cmd, NULL); } }
编译运行后,在弹出暂停提示时,打开新终端执行:
- 查看父进程文件描述符:
ls -l /proc/<父进程PID>/fd - 查看子进程文件描述符:先通过
ps -ef | grep myprog找到子进程PID,再执行ls -l /proc/<子进程PID>/fd
此时能清晰看到未关闭的my_fd。
方案2:用strace追踪系统调用
直接用strace监控进程的文件描述符相关系统调用,即使进程快速退出也能捕获完整记录:
strace -e dup,dup2,close ./myprog
输出会明确展示dup创建的文件描述符编号,以及后续是否执行了close操作,直接验证是否存在未关闭的描述符。
方案3:替换exec为长期运行的程序
把子进程要执行的/bin/ls换成/bin/sleep 60,让子进程存活60秒,足够你用工具查询:
cmd[0] = "/bin/sleep"; cmd[1] = "60"; cmd[2] = NULL;
运行后执行lsof -p <子进程PID>,就能看到继承的未关闭文件描述符。
补充说明
进程执行execve时,未设置FD_CLOEXEC标志的文件描述符会被继承。你的代码中my_fd未设置该标志,所以子进程exec后会保留这个描述符,只是因为ls执行太快才无法被常规工具捕获。
内容的提问来源于stack exchange,提问作者a k
相关产品推荐
相关产品推荐

