I am writing a small program to list the file descriptors of a specific process, and I am having a hard time understanding the results. The process I'm inspecting looks like this:
int main() {
int fds1[2];
int fds2[2];
pipe(fds1);
pipe(fds2);
pid_t pid = fork();
if (pid == 0) {
dup2(fds1[0], STDIN_FILENO);
dup2(fds2[1], STDOUT_FILENO);
close(fds1[0]);
close(fds1[1]);
close(fds2[0]);
close(fds2[1]);
sleep(2);
return 0;
}
close(fds1[0]);
close(fds2[1]);
waitpid(pid, NULL, 0);
return 0;
}
The fd inspection program code looks like:
let path_str = format!("/proc/{}/fd", self.pid);
let dir = Path::new(&path_str);
let mut fds = Vec::new();
for entry in fs::read_dir(dir).ok()? {
let path = entry.ok()?.path();
let filename = path.file_name()?;
let fd = fname.to_str()?.to_string().parse::<usize>().ok()?
fds.push(fd);
}
The results of ls -l /proc/{pid}/fd while running the above programs together give me this list:
0 -> /dev/pts/6
1 -> /dev/pts/6
2 -> /dev/pts/6
22 -> /dev/pts/1
30 -> /dev/pts/4
4 -> /home/{user}/.spectrwm.conf
5 -> 'pipe:[168640]'
6 -> 'pipe:[168641]'
I'm confused as to why there are 5 symlinks to /dev/pts/x and why the bottom 3 fds are included in this process's file descriptors, especially my WM's config file. I have a basic understanding of how pipe and fork work, but I can't seem to understand what's going on here.
Any help or insight would be appreciated, thanks!