Process deepcopy管道连接?

时间:2018-06-13 07:47:46

标签: python multiprocessing

在Python多处理中,我看到一些代码执行以下操作

def worker(parent_conn, child_conn):
    parent_conn.close()

    while True:
        x = child_conn.recv()

        if x == 'close':
            child_conn.close()
            break
        else:
            do something

# Following as master

parent_conn, child_conn = Pipe()
process = Process(target=worker, args=[parent_conn, child_conn])

process.start()

child_conn.close()  # not used

for _ in range(10):
    parent_conn.send(something)
    parent_conn.recv()

parent_conn.send('close')

process.join()

我的问题是

  1. 为什么在worker中,我们可以直接关闭父连接,它应该已经破坏了管道。那么进程fork(deepcopy)是否为worker提供了父连接和子连接?

  2. 为什么在主程序中,我们也可以直接关闭child_conn,原因与上述问题相同?

  3. 如果我没有从父连接向工作人员发送'close',那么即使我在主程序中加入进程,while循环也会无限循环。

1 个答案:

答案 0 :(得分:0)

Pipe()创建了两个连接,它们如何传播到子进程取决于所使用的操作系统的实现。

在* nix系统上,fork()用于生成一个新进程,该进程从父进程继承所有打开的文件描述符。最佳做法是立即关闭分叉后不需要的所有继承文件描述符,这就是在这里完成的操作。这在没有fork()(窗口)的系统上没有意义,其中连接以不同方式实现,但它仍然有效。

父级和工作者都关闭了他们未使用的连接的一端。由于它们是单独的进程,因此在父级中调用child_conn.close()对工作中的child_conn没有影响,它只关闭连接的一端,另一端仍然可以使用。因此,工作人员可以在recv()上调用client_conn来获取使用parent_conn.send()在父级中发送的对象,反之亦然。

您的示例实际上不起作用,因为在主要过程中,在连接关闭后调用child_conn.recv()。这将引发异常。

process.join()等待进程完成,只有在循环结束时才会执行,所以如果你从不发送'close'消息,那么woker将无限期地阻塞child_conn.recv(),{ {1}}永远不会回来。这是一个典型的僵局。

指示工作人员退出的另一种方式是呼叫join()而不是发送关闭消息。这将导致parent_conn.close()引发EOF错误,但前提是所有进程(包括worker)都关闭了基础文件描述符,这是习惯上关闭不需要的文件描述符的一个原因。