我正在编写一个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消失了? 谢谢
答案 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
目录的打开句柄。