![标准输入、输出和错误文件描述符在 Linux 中何时何地首次打开?](https://linux22.com/image/224783/%E6%A0%87%E5%87%86%E8%BE%93%E5%85%A5%E3%80%81%E8%BE%93%E5%87%BA%E5%92%8C%E9%94%99%E8%AF%AF%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E5%9C%A8%20Linux%20%E4%B8%AD%E4%BD%95%E6%97%B6%E4%BD%95%E5%9C%B0%E9%A6%96%E6%AC%A1%E6%89%93%E5%BC%80%EF%BC%9F.png)
stdin、stdout 和 stderr (fds) 在哪里第一的打开?是内核做的吗?符号链接 /dev/std{in,out,err} 是何时何地创建的?执行此操作的代码在哪里?
我假设它在 linux 内核源代码中,但即使在 archlinux 6.5.3-arch1-1 linux 内核 github 存储库中搜索后,我也无法找到它发生的位置。
编辑:请问,如果您对这个问题投反对票,您能否解释一下原因,以便我可以做得更好?我真的很想知道这个问题。找到答案并不容易。
答案1
当进程启动时,操作系统执行的部分工作是创建管理进程文件描述符的数据结构,并且在常见情况下,使用指向其控制终端设备的指针填充描述符 0、1 和 2。某些进程是使用链接到与终端不同的设备(通常是 /dev/null 设备)的文件描述符启动的。某些进程将一个或多个文件描述符链接到一个接口,该接口通向另一个进程(通常是管道)或一个文件(即“重定向”)。虽然父进程可能会在生成子进程之前调用函数来打开这些描述符的文件/管道,但它仍然是管理跟踪文件描述符的数据结构的内核。如果你需要了解这种细节,一本关于 Unix/Linux 内部原理的书可以告诉你。
每个进程都有自己单独的文件描述符列表,因此没有一些通用的描述符或设备文件集可以指向并说它们是在某个特定日期/时间创建的。进程的描述符是在该进程启动时创建的,并且新进程会启动很多,因此文件描述符一直在创建。 (当进程退出并且操作系统在其后清理时被销毁)
您询问 /dev/stdin、/dev/stdout 和 /dev/stderr。这些是虚拟设备(通常称为“逻辑”设备)而不是物理设备。如果您使用类似的命令查看它们,ls -l /dev/stdin
您会发现它是指向另一个文件(例如/proc/self/fd/0
.看一下/proc/self
,您会发现它是一个指向数字目录的符号链接 - 事实上,ls
它是您要求 shell 调用的程序的数字进程 ID。如果您打开另一个终端并列出其/proc/self
,您将看到它指向一个不同的进程 ID,即ls
由第二个终端的 shell 调用的进程 ID。/dev/stdin
、/dev/stdout
和链接/dev/stderr
是在某个特定时间创建的,但它们指向一组目录,其中目录和文件实际上是围绕管理进程的内核数据结构的视图。这些数据结构对于不同的进程具有不同的值(例如进程ID),并且随着进程的启动和终止,新的部分被创建和删除。
我没有否决你的问题,但我的猜测是,这个看似简单的问题实际上需要大量的内部知识才能准确回答。这在内核源代码中并不是显而易见的。这就是为什么我提到要买一本关于内部原理的书来帮助你深入研究它。这种问答论坛有局限性,关于操作系统内部结构的扩展教程式答案不太适合这里。
答案2
不,内核不在乎。在进入 main() 之前,它们在早期启动用户空间代码中打开