execve 不继承任何文件描述符
execve does not inherit any filedescriptor
我正在编写 shell 并尝试实现 process substitution。
fork 继承所有文件描述符、分配的内存等。我知道 execve 也应该保留这种信息,因此只要未设置 O_CLOEXEC 标志,就保留每个打开的文件描述符。
我尝试了一个简单的 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']
fork 之后,我保留了相同的 fd table,但是每当我在 executable 上使用 execve 时,我都丢失了并且默认打开了 fd。
为什么打开的 fd 消失了?
谢谢
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
目录的打开句柄。
我正在编写 shell 并尝试实现 process substitution。 fork 继承所有文件描述符、分配的内存等。我知道 execve 也应该保留这种信息,因此只要未设置 O_CLOEXEC 标志,就保留每个打开的文件描述符。
我尝试了一个简单的 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']
fork 之后,我保留了相同的 fd table,但是每当我在 executable 上使用 execve 时,我都丢失了并且默认打开了 fd。 为什么打开的 fd 消失了? 谢谢
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
目录的打开句柄。