Python close_fds不清楚

Lui*_*rzi 8 python process file-descriptor parent-child

close_fds在Python27中遇到了一个问题,所以在做了一些研究后我发现了这个例子:

from subprocess import Popen, PIPE, STDOUT
p1 = Popen(['cat'], stdin=PIPE, stdout=PIPE)
p2 = Popen(['grep', 'a'], stdin=p1.stdout, stdout=PIPE)
p1.stdin.write("aaaaaaaaaaaaaaaa\n")
p1.stdin.close()
p2.stdout.read()
Run Code Online (Sandbox Code Playgroud)

我的问题是,我无法理解为什么p1.stdin仍然开放.p1不是孩子,p2所以p2不应该继承任何明确传递的p1资源p1.stdout.此外,为什么设置close_fds=Truep2解决问题?是写的:

如果close_fds为true,则在执行子进程之前将关闭除0,1和2之外的所有文件描述符.

因此,即使我能够理解它之间的继承p1,p2仍然p1.stdin不应该被关闭,close_fds=True因为它是标准输入(1).

use*_*342 13

由于p1p2是兄弟,没有直接继承其相应的进程之间的事情.

但是,请考虑父查看p1.stdin,继承p1并重定向到其的文件描述符stdin.这个文件描述符存在于父进程中(使用0,1或2之外的数字 - 你可以通过打印来验证它p1.stdin.fileno()),它必须存在,因为我们打算从父进程写入它.这个文件描述符是无意中继承并保持打开状态的p2.

当多个文件描述符引用打开的文件时,就像这样p1.stdin,只有在关闭所有描述符时才会关闭它.这就是为什么有必要都接近p1.stdin 传递close_fdsp2.(如果您手动实现了产生代码,则只需在第二个之后关闭文件描述符fork().)

  • @LuigiTiburzi`p1.stdin`及其文件描述符是同一个底层资源(文件描述符 - 指针无关紧要,因为打开文件是内核分配的操作系统级资源).`p2`进程继承文件描述符,该副本保持打开状态.这就是关闭`p1.stdin`(也不是它的文件描述符)没有帮助的原因.您可以将文件描述符视为"打开文件"的引用 - 关闭描述符会删除对打开文件的单个引用.只有当所有文件描述符都关闭时,打开的文件才真正关闭. (5认同)
  • @LuigiTiburzi这是一种传递引用,因为所有fd都指向相同的开放文件资源.但是底层资源是引用计数的,所以只有当*all*的引用被关闭时它才会被关闭. (4认同)
  • @LuigiTiburzi`p1.stdin`是fd周围的Python对象包装器-它们是相同的。您可以关闭p2的描述符,但Python不会授予您对p2的控制权。这就是为什么close_fds解决此问题的原因。 (2认同)