在Java中创建命名管道

6

我正在使用Java创建命名管道进行实验,操作系统是Linux。然而,我遇到了一个问题:向管道写入数据时程序会挂起。

    File fifo = fifoCreator.createFifoPipe("fifo");
    String[] command = new String[] {"cat", fifo.getAbsolutePath()};
    process = Runtime.getRuntime().exec(command);

    FileWriter fw = new FileWriter(fifo.getAbsoluteFile());
    BufferedWriter bw = new BufferedWriter(fw);
    bw.write(boxString); //hangs here
    bw.close();
    process.waitFor();
    fifoCreator.removeFifoPipe(fifo.toString());

fifoCreator:

@Override
public File createFifoPipe(String fifoName) throws IOException, InterruptedException {
    Path fifoPath = propertiesManager.getTmpFilePath(fifoName);
    Process process = null;
    String[] command = new String[] {"mkfifo", fifoPath.toString()};
    process = Runtime.getRuntime().exec(command);
    process.waitFor();
    return new File(fifoPath.toString());
}

@Override
public File getFifoPipe(String fifoName) {
    Path fifoPath = propertiesManager.getTmpFilePath(fifoName);
    return new File(fifoPath.toString());
}

@Override
public void removeFifoPipe(String fifoName) throws IOException {
    Files.delete(propertiesManager.getTmpFilePath(fifoName));
}

我正在编写一个由1000行组成的字符串。写入100行可以工作,但写入1000行会出现问题。

然而,如果在外部shell上运行“cat fifo”,那么程序就可以继续执行并将所有内容都写出来,而不会挂起。这个程序启动的cat子进程无法正常工作,很奇怪。

编辑:我对子进程进行了ps查询,它的状态为“S”。

1个回答

9

外部进程具有输入和输出,您需要处理它们。否则,它们可能会挂起,尽管它们挂起的确切时间点会有所不同。

解决问题的最简单方法是更改每个出现的内容:

process = Runtime.getRuntime().exec(command);

转换为:

process = new ProcessBuilder(command).inheritIO().start();

Runtime.exec是已过时的,应该使用ProcessBuilder代替。

更新:

inheritIO()是简写,用于将所有进程的输入和输出重定向到父Java进程的输入和输出。您可以选择仅重定向输入,并自己读取输出:

process = new ProcessBuilder(command).redirectInput(
    ProcessBuilder.Redirect.INHERIT).start();

那么,您需要从process.getInputStream()中读取进程的输出。

这个可以运行。不过,我该如何获得进程的输出呢?在此之前,我一直在使用 process.getInputStream()。 - mrQWERTY
如果您知道将使用process.getInputStream()读取输出,那么可以选择仅重定向进程的输入。相应地更新答案。 - VGR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接