/dev/fd/3 有一些特别之处

/dev/fd/3 有一些特别之处

我一直在尝试了解文件描述符。当我输入“ls -l /dev/fd/”时,我得到

lrwx------ 1 me users 64 May  2 16:02 0 -> /dev/pts/5
l-wx------ 1 me users 64 May  2 16:02 1 -> /home/me/file
lrwx------ 1 me users 64 May  2 16:02 2 -> /dev/pts/5
lr-x------ 1 me users 64 May  2 16:02 3 -> /proc/31518/fd

/dev/fd/3 似乎指向当前进程。但是,我见过的文件描述符的解释,例如 http://www.tldp.org/LDP/abs/html/io-redirection.html,不要说 /dev/fd/3 有什么特别之处(并暗示它就像 N > 3 的任何 /dev/fd/N 一样)。这里发生了什么?

我在 arch linux 和 ubuntu 上观察到了这一点,但在我有 ssh 帐户的 solaris 服务器上没有观察到这一点。

答案1

/dev/fd/3 似乎指向当前进程。

即,ls它本身(请注意,之后 pid 将不存在)。所有这些实际上都属于当前进程,因为文件描述符不是全局的;整个系统不只有一个 0、1 和 2,每个进程都有单独的 0、1 和 2。

正如 Frederik Dweerdt 所指出的,/dev/fd是一个符号链接。如果您ls从不同的终端重复您的操作,您会注意到指向不同 pty 的链接。这些将与命令的输出匹配tty

在这个ls例子中,我想象描述符 3 是用来读取文件系统的。一些 C 命令(例如open())支持文件描述符的生成,保证返回“编号最低的未使用文件描述符”POSIX-- 请注意,低级 open() 实际上不是标准 C) 的一部分。所以它们在关闭后会被回收(如果你反复打开和关闭不同的文件,你会一遍又一遍地得到3作为fd)。

如果您想了解它们是如何存在的,这里有一段使用 的 C 代码片段opendir(),您可能会在 ls 的源代码中找到它:

// open directory for reading
DIR *dh = opendir(".");
// print the fd of the directory handle to standard out:
printf("fd: %d\n", dirfd(dh));
closedir(dh);  

按原样运行,fd 将为 3,因为这是最低的未使用描述符(0、1 和 2 已经存在)。

答案2

/dev/fd/3不是标准描述符(编辑:赋值)。它(编辑:超过 0、1 和 2)特定于您的情况 ( ls)。您可以通过 strace 运行 ls 来了解发生了什么:

strace -e trace=openat,readlink ls -l /dev/fd/
openat(AT_FDCWD, "/dev/fd/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
readlink("/dev/fd/0", "/dev/pts/0", 65) = 10
readlink("/dev/fd/1", "/dev/pts/0", 65) = 10
readlink("/dev/fd/2", "/dev/pts/0", 65) = 10
readlink("/dev/fd/3", "/proc/28401/fd", 65) = 14

ls/dev/fd就是显示和 一样的内容/proc/self/fdls必须打开该目录才能读取其条目。/dev/fd/3只是该目录的文件描述符。

其他程序没有/dev/fd/3

start cmd:> sleep 100 &
[1] 28414

ec:0   17:28:10  hl@inno:~/.wine/drive_c
start cmd:> ls -l /proc/28414/fd
insgesamt 0
crw------- 1 hl tty 136, 0 18. Apr 01:18 0
crw------- 1 hl tty 136, 0 18. Apr 01:18 1
crw------- 1 hl tty 136, 0 18. Apr 01:18 2

答案3

在 Archlinux 上,/dev/fd是一个到/proc/self/fd.您看到的是命令fd的目录ls。该命令确实将目录打开为文件描述符 3。

编辑:顺便说一句,了解正在发生的事情的一个好方法是使用strace.您将看到打开文件描述符的进程。

相关内容