execve()和共享文件描述符

9

我从execve的man页中读到,如果一个进程(A)调用execve,那么已经打开的文件描述符会被复制到新的进程(B)。

这里有两种可能性:

1)这是否意味着为进程B创建了一个新的文件描述符表,其条目从进程A的旧文件描述符表中复制而来?

2)或者进程B获得了进程A的文件描述符表,因为在执行execve后,进程A将不再存在,已经打开的文件只能从进程B关闭,如果它获得了进程A的文件描述符表。

哪一个是正确的?

2个回答

22

execve 不会创建新的进程。它会使用文件系统中可执行文件替换调用进程的程序镜像、内存空间等内容,描述符表也会被修改,关闭任何设置了 close-on-exec 标志的描述符;其余的描述符保持打开状态,并且与 execve 前一样(当前位置、锁等)。

你可能把这个和 fork 发生的事情混淆了,因为 execve 通常是在 fork 之后发生的。当一个进程 fork 时,子进程拥有一个新的文件描述符表,引用与父进程相同的打开文件描述符。


1
我认为这是@stackoverflow.com的一个严重限制,虽然两个答案都是正确的,但我只能标记其中一个为绿色。 - Ashish
@Ashish 现在您可以为它们投上赞成票。您可能希望现在将此答案标记为被采纳的答案。 - Josiah Yoder

9
哪一个是正确的?
#2
虽然你所问的更多是操作系统实现细节,这对应用程序来说很少甚至从来不重要,完全透明于应用程序并且取决于操作系统。
通常说新进程会“继承”文件描述符。当然,除了那些设置了FD_CLOEXEC标志的文件描述符。
即使在情况1下,假设某个短时间内进程A和B都在内存中(实际上不是这样,那是fork()领域),复制fd表也是可以的。由于进程A将被exec()终止,所有它的文件描述符都将被close()。这不会影响已经复制到进程B中的文件描述符。文件描述符就像指向相应内核结构的指针,该内核结构包含有关文件描述符实际指向的内容的实际信息。复制fd表不会复制底层结构的副本-它只复制指针。内核结构包含引用计数器(实现fork()所需),当进行复制时会增加,因此知道有多少进程正在使用它。首先调用close()对文件描述符进行减量。仅当计数器变为零(没有更多进程使用该结构)时,操作系统才会实际关闭底层文件/套接字/管道等。(但显然,即使在内核中有两个进程同时存在一段时间,用户空间应用程序也无法看到这一点,因为经过exec()后,新进程也会继承原始进程的PID。)

第二段是最好的("inherits"文件描述符)。我在阅读最后一段时迷失了。 - Josiah Yoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接