execve不继承任何filedescriptor

时间:2019-06-20 16:21:17

标签: python python-3.x unix file-descriptor execve

我正在编写一个shell并尝试实现process substitution。 派生所有文件描述符,分配的内存等的继承。我了解到,只要未设置O_CLOEXEC标志,execve也应保留此类信息,因此应保留每个打开的文件描述符。

我尝试了一个简单的python脚本:
fd.py:

#!/usr/bin/env python3
import sys, os

if __name__ == "__main__":
    if len(sys.argv) == 1:
        new_fd = open("the_content_file", "w+")
        print("father table : ", os.listdir("/dev/fd"))
        if os.fork() == 0:
            os.execve("/PATH/OF/SCRIPT/fd.py", ["fd", "content"], os.environ)
    else:
        print("child table : ", os.listdir("/dev/fd"))
    pass

作为输出,我得到:

father table :  ['0', '1', '2', '3', '4']
child table :  ['0', '1', '2', '3']

在派生之后,我保留了相同的fd表,但是每当我在可执行文件上使用execve时,我都会丢失所有文件并默认打开fd。 为什么打开的fd消失了? 谢谢

1 个答案:

答案 0 :(得分:2)

python3(自3.4版开始,与python2不同)默认情况下使用O_CLOEXEC标志打开文件。

我不是python程序员,但是关闭文件上的O_CLOEXEC的简单方法可以是在new_fd = ..行之后添加:

        os.set_inheritable(new_fd.fileno(), True)

(已在python 3.6.6上测试,请参见文档here

或者在3.5.3之类的旧版本上:

        tmp_fd = os.dup(new_fd.fileno())
        os.dup2(tmp_fd, new_fd.fileno())
        os.close(tmp_fd)

(默认情况下,os.dup2用于将目标设为fd inheritable

请注意,尽管您已为其命名,但new_fd并不是文件描述符,而是python流。您在父级和子级中都看到的额外文件是/dev/fd目录的打开句柄。