Python和FIFO

时间:2011-02-22 21:30:41

标签: python linux fifo broken-pipe mkfifo

我试图在Linux下使用Python来理解FIFO,我发现了一个我不理解的奇怪行为。

以下是fifoserver.py

import sys
import time

def readline(f):
    s = f.readline()
    while s == "":
        time.sleep(0.0001)
        s = f.readline()
    return s

while True:
    f = open(sys.argv[1], "r")
    x = float(readline(f))
    g = open(sys.argv[2], "w")
    g.write(str(x**2) + "\n")
    g.close()
    f.close()
    sys.stdout.write("Processed " + repr(x) + "\n")

这是fifoclient.py

import sys
import time

def readline(f):
    s = f.readline()
    while s == "":
        time.sleep(0.0001)
        s = f.readline()
    return s

def req(x):
    f = open("input", "w")
    f.write(str(x) + "\n")
    f.flush()
    g = open("output", "r")
    result = float(readline(g))
    g.close()
    f.close()
    return result

for i in range(100000):
    sys.stdout.write("%i, %s\n" % (i, i*i == req(i)))

我还使用mkfifo inputmkfifo output创建了两个FIFO。

我不明白为什么当我在一些请求之后运行服务器(带python fifoserver.py input output)和客户端(带python fifoclient.py)来自两个控制台时客户端崩溃时出现“断管” f.flush()上的错误。请注意,在崩溃之前,我已经看到从几百到几千个正确处理的请求运行正常。

我的代码中有什么问题?

2 个答案:

答案 0 :(得分:5)

正如其他评论所暗示的那样,你有竞争条件。

我怀疑在失败的情况下,服务器会在其中一行之后被暂停:

g.write(str(x**2) + "\n")
g.close()

然后,客户端可以读取结果,将其打印到屏幕上,然后循环返回。然后重新打开f - 成功,因为它仍在服务器端打开 - 并写入消息。同时,服务器已成功关闭f。接下来,客户端上的刷新在管道上执行write()系统调用,触发SIGPIPE,因为它现在在另一侧关闭。

如果我没错,您应该可以通过将服务器的f.close()移到g.write(...)之上来解决问题。

答案 1 :(得分:0)

我不是unix专家,但我的猜测是你最终会在两个进程中关闭文件,接下来会发生open-for-write。由于没有什么可以接受数据,管道中断了。

我不明白你为什么一直打开和关闭管道。

首先尝试启动读取管道的进程,让它打开管道并等待数据。

然后启动管道编写器,并将其抽出所有要发送的数据。如果它领先,它将停滞不前。当编写器关闭管道时,读取器获得零字节而不是阻塞,并且应该关闭。 IIRC,Python检测到这一点并返回EOF。