fork() 是否还会复制调用进程当前正在执行的可执行二进制文件的文件描述符?

fork() 是否还会复制调用进程当前正在执行的可执行二进制文件的文件描述符?

我读过 fork() 的手册页,他们说了一些类似“调用进程中打开的所有文件描述符都被复制”的内容。

我并不是 100% 清楚调用进程在该时间点正在执行的可执行二进制文件的文件描述符是否包含在该语句中。我知道手册页说“所有文件描述符”,但我问这个是因为对我来说,为分叉进程使用相同的可执行二进制文件似乎更容易open(),而不是同步使用它们的两个进程。那么,如果它们确实也被复制,为什么呢?

答案1

正在执行的二进制文件没有文件描述符,只有内存映射。

(参见,例如Linux 上的ls -l /proc/self/fdcat /proc/self/maps。)

当然,内存映射将指向同一个文件,但这也是共享库发生的情况。对于主程序文件,在 Linux 上,不允许在正在运行的进程使用它时对其进行写入。 (虽然我上次检查时发现这不适用于共享库。)

答案2

目前尚不清楚您实际上想要做什么,但在 Linux(和其他一些系统)上,您可以使用open("/proc/self/exe", ...).即使文件已被删除或文件系统中从未存在过,这也将起作用。

就像/dev/tty(它将始终打开调用进程的控制 tty——如果有的话)一样,/proc/self/exe将始终打开调用进程当前正在执行的文件。它们都充当进程已引用的隐藏打开文件描述的“门”,允许像普通文件一样访问它们。

这些并不是进程拥有的唯一“隐藏”/潜在文件描述符。特别是,您可以使用 创建文件的内存映射mmap(..., fd, ...),然后关闭fd不会删除该映射,并且您的进程仍将保留对该文件的引用,就像文件描述符一样(在 Linux 上,您可以将其转回通过打开进入文件描述符/proc/self/map_files/<range>)。


其他示例是根目录和当前工作目录 ( /proc/self/{cwd,root}) ——不过,就像任何目录一样,即使是通过 open fds 引用的目录,它们的语义也与常规文件的语义不同 —— 特别是,您不能在已删除的目录中创建文件。目录,您可以通过其仍打开的文件描述符继续将数据写入已删除的文件。

相关内容