Linux - 命名管道 - 丢失数据

时间:2011-02-01 20:47:02

标签: linux groovy

我正在使用IPC的命名管道。有时,进程之间发送的数据可能很大且频繁。在这段时间里,我看到很多数据丢失。以下代码中是否存在可能导致此问题的明显问题?

由于

#!/usr/bin/env groovy
import java.io.FileOutputStream;
def bytes = new File('/etc/passwd').bytes
def pipe = new File('/home/mohadib/pipe')
1000.times{
    def fos = new FileOutputStream(pipe)
    fos.write(bytes)
    fos.flush()
    fos.close()
}


#!/usr/bin/env groovy
import java.io.FileInputStream;
import java.io.ByteArrayOutputStream;

def pipe = new File('/home/mohadib/pipe')
def bos = new ByteArrayOutputStream()
def len = -1
byte[] buff = new byte[8192]
def i = 0
while(true)
{
    def fis = new FileInputStream(pipe)
    while((len = fis.read(buff)) != -1) bos.write(buff, 0, len)
    fis.close()
    bos.reset()
    i++
    println i
}

2 个答案:

答案 0 :(得分:2)

本节让我担心:

1000.times{
    def fos = new FileOutputStream(pipe)
    fos.write(bytes)
    fos.flush()
    fos.close()
}

我知道底层的Unix write()系统调用并不总是写入请求的字节数。您必须检查返回值以查看实际写入的数字。

我检查了Java的文档,看来fos.write()没有返回值,如果出现任何问题,它只会抛出IOException。 Groovy对异常做了什么?有没有例外?

如果可以,请在strace下运行此命令并查看读写系统调用的结果。 Java VM可能没有使用write()系统调用做正确的事情。我知道这可能发生,因为两年前我抓住了glibc的fwrite实现(忽略了返回值)。

答案 1 :(得分:2)

当最后一个进程关闭时,命名管道会丢失其内容。在您的示例中,如果编写器进程在读取器进程即将执行fis.close()时执行另一次迭代,则会发生这种情况。在这种情况下没有报告错误。

可能的解决方法是安排读者进程永远不会关闭fifo。要在最后一个写入程序断开连接时摆脱EOF条件,请打开fifo进行写入,关闭读取结束,重新打开读取结束并关闭临时写入结束。