execve()和共享文件描述符

时间:2010-07-05 13:01:56

标签: c operating-system

我从execve的man页面读到,如果进程(A)调用execve,则已打开的文件描述符将被复制到新进程(B)。

这里出现两种可能性: -

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

2)或者进程B获取进程A的文件描述符表,因为执行进程A将停止存在,并且已经打开的文件只能从进程B关闭,如果它获得进程A的文件描述符表。 / p>

哪一个是正确的?

2 个答案:

答案 0 :(得分:17)

execve不会创建新流程。它根据文件系统中的可执行文件用新的替换调用进程的程序映像,内存空间等。通过使用close-on-exec标志设置关闭任何描述符来修改文件描述符表;其余部分保持开放状态,处于execve之前的状态(当前位置,锁定等)。

您可能会对fork上发生的事情感到困惑,因为execve通常在fork之后。当进程分叉时,子进程有一个新的文件描述符表,引用与父进程的文件描述符表相同的打开文件描述。

答案 1 :(得分:7)

  

哪一个是正确的?

#2

虽然您要求的更多是操作系统实现细节,但对应用程序来说很少有用,对应用程序完全透明,取决于操作系统。

通常说新进程继承文件描述符。除了设置了FD_CLOEXEC标志的那些,显然。

即使在#1的情况下,如果我们假设在一段短时间内进程A和B都在内存中(不是真的,那就是fork()区域)复制fd表就可以了。由于进程A将被终止(通过exec()),它的所有文件描述符都将是close()d。这对过程B中已经复制的文件描述符没有影响。文件描述符就像指向相应内核结构的指针,包含有关文件描述符实际指向的实际信息。复制fd表不会复制底层结构 - 它只复制指针。内核结构包含引用计数器(实现fork()所需),它在复制时递增,因此知道有多少进程正在使用它。首先在文件描述符上调用close()会减少引用计数器。并且只有当计数器变为零(没有更多进程正在使用该结构)时,OS才会实际关闭底层文件/套接字/管道/等。 (但显然即使内核内部有两个进程同时存在两个短时间,用户空间应用程序也看不到,因为exec()之后的新进程也继承了原始进程的PID。)