我一直在尝试了解文件描述符。当我输入“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/fd
。ls
必须打开该目录才能读取其条目。/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
.您将看到打开文件描述符的进程。