如何忽略由read_dir创建的文件描述符?
我试图通过访问 /proc/[process_pid]/fd 来列出某个进程打开的所有文件描述符。
我的代码:
pub fn list_fds(&self) -> Option<Vec<usize>> {
let mut fd_vec: Vec<usize> = Vec::new();
let linux_process_fd_path_string = format!("/proc/{}/fd", self.pid);
let linux_process_fd_path = Path::new(&linux_process_fd_path_string);
let entries = fs::read_dir(linux_process_fd_path).ok()?;
if linux_process_fd_path.is_dir() {
for entry in entries {
let entry = entry.ok()?;
let filename_uszie = entry.file_name().to_string_lossy().parse::<usize>().ok()?;
fd_vec.push(filename_uszie);
}
}
//fd_vec.pop(); // I don't know if this is appropriate to ignore fd created by read_dir
Some(fd_vec)
}
测试代码:
#[test]
fn test_list_fds() {
let mut test_subprocess = start_c_program("./multi_pipe_test");
let process = ps_utils::get_target("multi_pipe_test").unwrap().unwrap();
assert_eq!(
process
.list_fds()
.expect("Expected list_fds to find file descriptors, but it returned None"),
vec![0, 1, 2, 4, 5]
);
let _ = test_subprocess.kill();
}
输出:
---- process::test::test_list_fds stdout ----
thread 'process::test::test_list_fds' (52275) panicked at src/process.rs:75:9:
assertion `left == right` failed
left: [0, 1, 2, 4, 5, 103]
right: [0, 1, 2, 4, 5]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
然后我发现该函数在调用read_dir时可能会创建一个文件描述符。
我尝试去掉最后一个文件描述符,但不确定是否合适(显然不可取)。
忽略这个文件描述符的最佳实践是什么?
解决方案
dirfd() 函数返回DIR结构体的底层文件描述符。
下面是一个简单的C 程序,显示 "/proc/opendir() 服务对应的条目:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
DIR *dd;
struct dirent *de;
ssize_t sz;
char myFdDir[256];
char buf[256];
int rc, rc1;
char fdToExclude[20];
int fd;
// My fd list directory
rc = snprintf(myFdDir, sizeof(myFdDir), "/proc/%d/fd", getpid());
// Open my fd list directory (this creates a brand-new file descriptor)
dd = opendir(myFdDir);
snprintf(fdToExclude, sizeof(fdToExclude), "%d", dirfd(dd));
// Read the content of the directory
while ((de = readdir(dd)))
{
// Ignore current and father directories
if (!strcmp(de->d_name, ".") ||
!strcmp(de->d_name, ".."))
continue;
// Ignore fd of opendir()
if (!strcmp(fdToExclude, de->d_name))
continue;
// Absolute pathname of the symbolic link
rc1 = snprintf(&(myFdDir[rc]), sizeof(myFdDir) - rc, "/%s", de->d_name);
// Get the content of the symbolic link
sz = readlink(myFdDir, buf, sizeof(buf));
buf[sz] = '\0';
// Restore my fd list directory name
myFdDir[rc] = '\0';
printf("%s -> %s\n", de->d_name, buf);
}
closedir(dd);
return 0;
}
$ gcc myfds.c -o myfds
$ ./myfds
0 -> /dev/pts/3
1 -> /dev/pts/3
2 -> /dev/pts/3
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。