在/proc/self
寻找我的mksh
shell 的文件夹时,我发现了一件奇怪的事情:在/proc/self/fd/*
所有标准文件描述符中(0 表示标准输入,1 表示标准输出,2 表示标准错误)一些文件描述符,但也有一些额外的 - 24、25、3 .而且从技术上讲,我可以在 shell 中用一个 glob 列出它们:
$ for fd in /proc/self/fd/* ; do echo $fd ; done
/proc/self/fd/0
/proc/self/fd/1
/proc/self/fd/2
/proc/self/fd/24
/proc/self/fd/25
/proc/self/fd/3
但是当我尝试stat
使用它们或使用find
它们时,它们被报告为不存在。
$ find /proc/self/fd/*
/proc/self/fd/0
/proc/self/fd/1
/proc/self/fd/2
find: ‘/proc/self/fd/24’: No such file or directory
find: ‘/proc/self/fd/25’: No such file or directory
/proc/self/fd/3
同样发生在 中bash
,但只有一个辅助文件描述符。
$ for fd in /proc/self/fd/* ; do echo $fd; done
/proc/self/fd/0
/proc/self/fd/1
/proc/self/fd/2
/proc/self/fd/255
/proc/self/fd/3
$ find /proc/self/fd/*
/proc/self/fd/0
/proc/self/fd/1
/proc/self/fd/2
find: ‘/proc/self/fd/255’: No such file or directory
/proc/self/fd/3
问题是:那些额外的文件描述符是什么?他们的目的是什么?
探测
/proc/self
是一项棘手的工作,因为它会随着每个流程而变化。当您这样做/proc/self/fd/*
时,shell 会扩展通配符,因此它会列出自己的文件描述符。但是当这些被传递给另一个命令时,比如find
orls
,路径现在将用于该进程'/proc/self
,并且它可能有也可能没有带有这些数字的 fds。更棘手的是,shell 可能会在通配符扩展期间打开文件描述符。
比较
/proc/$$/fd
可能很有启发性:bash
:通过将其发送到后台,我让 bash 打印 PID,您可以看到它
/proc/self/fd/3
指向ls
' own/proc/<PID>/fd
,它已打开以进行扫描。带有 OTOH 的条目4932
用于 bash 的 fds,特殊的是 255。在此 SO 帖子中可以找到解释:与
mksh
:几乎相同的东西,除了额外的 fd 是 10,我敢打赌它的原因与 bash 相同,因为源代码表明 shell 使用 fd 10 及更高版本。
我没有得到两个或三个额外的 fd,但这可能是由于通配符扩展期间发生的任何事情,或者由于后台作业或其他一些模糊的原因。
如果我运行你的
for
循环,我会得到一个短暂的 fd 3:在这里,
strace
用于跟踪执行:我们将看到第三个 fd 实际上是
/proc/<PID>/fd
:现在的问题是,为什么这个 fd 没有出现在早期的
ls
测试中?看起来背景与此有关:前景
ls
显示丢失的 fd。现在,再次跟踪
strace
:我们看:
注意 PID 的变化。似乎通配符扩展发生在分叉之后,但变量扩展发生在此之前。因此,fd 3 存在,但在不同的过程中。现在我使用
self
而不是$$
,您将看到 3 和 255:附录
Unix&Linux Stackexchange 网站上的相关答案引用了来自邮件列表的回复: