如何忽略read_dir读取/proc/[pid]/fd时创建的文件描述符?
解决/proc/[pid]/fd遍历中包含read_dir自身FD的问题
直接pop最后一个元素的做法完全不可靠——proc文件系统的目录遍历顺序没有任何保证,那个额外的FD未必会出现在列表末尾。正确的做法是在遍历过程中跳过read_dir自身对应的文件描述符,具体实现如下:
核心思路
当你调用read_dir打开/proc/[pid]/fd目录时,这个操作会在当前进程中创建一个新的FD(指向该目录)。如果是读取自身进程的FD(/proc/self/fd),这个新FD会被包含在遍历结果里;如果是读取其他进程的FD,这个FD属于当前进程,不会出现在目标进程的FD列表中,所以跳过操作不会影响结果。
Rust代码实现
use std::fs::read_dir; use std::os::unix::io::AsRawFd; use std::io; fn list_fds(pid: u32) -> io::Result<Vec<i32>> { let fd_dir_path = format!("/proc/{}/fd", pid); // 打开目标FD目录,获取ReadDir实例 let mut dir_iterator = read_dir(fd_dir_path)?; // 获取这个ReadDir自身对应的文件描述符 let dir_self_fd = dir_iterator.as_raw_fd(); let mut fds = Vec::new(); while let Some(entry) = dir_iterator.next() { let entry = entry?; // 将目录项名称转为字符串(即FD数字) let fd_str = entry.file_name().into_string().map_err(|_| { io::Error::new(io::ErrorKind::InvalidData, "无法解析FD名称") })?; if let Ok(fd) = fd_str.parse::<i32>() { // 跳过read_dir自身的FD if fd != dir_self_fd { fds.push(fd); } } } Ok(fds) }
其他注意事项
- 如果你只需要读取自身进程的FD,也可以先在打开
read_dir前通过一次遍历获取初始FD列表,但这种方法需要两次IO操作,效率不如直接跳过目标FD。 - 处理
/proc文件系统时要注意权限问题:如果目标进程不属于当前用户,你可能没有权限读取其fd目录。
内容的提问来源于stack exchange,提问作者jz steven
相关产品推荐
相关产品推荐

