多进程写入python

时间:2015-11-16 05:48:28

标签: python linux pipe

当多进程同时写入同一个管道时,我对结果感到困惑,这里是代码:

#!/bin/python

import os
import sys
import time
from multiprocessing import Pipe

# generate pipe pair
parent_conn, child_conn = Pipe()
count = 0
# 1MB
size = 1024 * 1024

for i in range(0, 2):
    ret = os.fork()
    if ret > 0:
        # child process
        if i == 0:
            while True:
                recv = child_conn.recv_bytes()
                open("/tmp/pipe_test/%s" % count, "w").write(recv)

        if i == 1:
            while True:
                if count == 1:
                    break
                parent_conn.send_bytes("1" * size)
                count += 1
            sys.exit(0)

while True:
    if count == 1:
        break
    parent_conn.send_bytes("%" * size)
    count += 1

进程将生成2个子进程,一个用于调用recv_bytes从管道获取数据,另一个用于向管道写入数据,主进程也会写入管道。因此有两个进程写入一个管道,一个进程接收数据然后写入本地文件。

我希望/tmp/pipe_test/中有2个文件,其中一个文件已满#34; 1"另一个是"%",每个都 1MB

但结果是:

只有一个文件/tmp/pipe_test/0 1MB ,有" 1"和"%"在那个文件中。奇怪的是,每个" 1"和"%"细分是 16KB ,我知道它可能与pipe man page中的系统页面尺寸相关联,但当我执行getconf PAGESIZE时我得到 4096 ,而不是 16KB

另一件事是,如果我将size变量设置为较小的数字(如1024),那么结果就是我想要的:/tmp/pipe_test/中的2个文件,每个文件都是1024,其中一个是"%"另一个持有" 1"。

如果有人可以解释一下,那将是很好的。

1 个答案:

答案 0 :(得分:0)

您似乎对如何使用fork感到困惑。例如,您不能按照描述的方式创建子流程。

fork将进程克隆到父进程和子进程中的作用是什么,它们是相同的,具有相同的状态,除了返回子进程0并且在父进程中子进程的id是返回表单fork

这意味着第一个进程中的循环将运行fork(创建一个子进程),但第一个子进程从fork返回时的状态仍然是一个循环运行,这样它将第二次运行循环并创建一个大子进程。

然后你有一个误导性的评论# child processret > 0仅在父进程中(或从第一个子进程,当它成为进程的子进程的父进程)时的分支。创建tmp/pipe_test/%d的分支仅在i == 0仅在循环的第一轮中发生时(并且仅在第一个过程中)进行,然后创建的文件为{ {1}}。

因此,流程执行以下操作:

  1. 创建子进程(2),然后它从tmp/pipe_test/0接收数据(对于所有进程都是相同的管道)并写入child_conn(因为/tmp/pipe_test/0并且你不改变它,它将在无限循环中完成。

  2. 子进程将运行第二轮循环,创建子进程(3),然后该进程将运行count==0分支,其中if i==1发送到1 1}}然后退出。

  3. 该过程将退出循环并将parent_conn写入%然后终止。

  4. 现在当你同时写入管道时会发生什么,你需要查阅parent_conn手册页。管道的缓冲区大小不需要与页面大小相同,管道缓冲区和pipe(7)的单独定义也是如此。如果您编写的块大于PIPE_BUF,则提到的数据是交错的,但它没有提到它将在PIPE_BUF块中。