当多进程同时写入同一个管道时,我对结果感到困惑,这里是代码:
#!/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"。
如果有人可以解释一下,那将是很好的。
答案 0 :(得分:0)
您似乎对如何使用fork
感到困惑。例如,您不能按照描述的方式创建子流程。
fork将进程克隆到父进程和子进程中的作用是什么,它们是相同的,具有相同的状态,除了返回子进程0
并且在父进程中子进程的id是返回表单fork
。
这意味着第一个进程中的循环将运行fork
(创建一个子进程),但第一个子进程从fork
返回时的状态仍然是一个循环运行,这样它将第二次运行循环并创建一个大子进程。
然后你有一个误导性的评论# child process
,ret > 0
仅在父进程中(或从第一个子进程,当它成为进程的子进程的父进程)时的分支。创建tmp/pipe_test/%d
的分支仅在i == 0
仅在循环的第一轮中发生时(并且仅在第一个过程中)进行,然后创建的文件为{ {1}}。
因此,流程执行以下操作:
创建子进程(2),然后它从tmp/pipe_test/0
接收数据(对于所有进程都是相同的管道)并写入child_conn
(因为/tmp/pipe_test/0
并且你不改变它,它将在无限循环中完成。
子进程将运行第二轮循环,创建子进程(3),然后该进程将运行count==0
分支,其中if i==1
发送到1
1}}然后退出。
该过程将退出循环并将parent_conn
写入%
然后终止。
现在当你同时写入管道时会发生什么,你需要查阅parent_conn
手册页。管道的缓冲区大小不需要与页面大小相同,管道缓冲区和pipe(7)
的单独定义也是如此。如果您编写的块大于PIPE_BUF
,则提到的数据是交错的,但它没有提到它将在PIPE_BUF
块中。