0

我有一些使用 stdio 进行输入和输出的旧 C++ 代码。该代码还通过分叉生成新进程。它将 stdio 重新映射到每个新进程,以便每个会话获取其各自的数据。

我正在研究使用 Java 中的线程来创建子进程。但是,在找出如何重新映射以及创建子线程时,我陷入System.in了困境System.outSystem.err

如果可能的话,谁能指出我正确的方向?

4

4 回答 4

1

生成线程与生成进程不同。当您在 java(和 c++)中生成线程时,它与生成器共享相同的内存空间(即它们共享相同的 sdio 流)。如果您想在 java 中生成一个新进程,您将使用 Runtime.exec() 然后您必须手动将 io 传输到新进程中,java 不支持跨进程边界共享 io 流。

于 2011-02-13T16:41:47.297 回答
1

简单的答案不是写你的代码直接访问 System.out/in/err。而是将一个InputStream和两个OutputStream传递给对象的构造函数。然后该对象直接与这些对象一起工作,而不依赖于它们实际映射到的对象。要访问print()and println(),您需要将OutputStreamin 传递给 a 的构造函数PrintStream

然后根据您实际想要做的事情,您可以使用 System.out 或一些 a 调用构造函数FileOutputStream

于 2011-02-13T16:25:58.000 回答
0

Java 没有 fork(),但它有 ProcessBuilder 和 Runtime.exec() 用于启动新进程(Process 类的对象)。您可以将其视为 fork()/exec() 对,但无法在 dup2() 之间执行某些操作。这意味着您不能重定向子进程的 stdio,但您可以使用相应的 Process 方法,或者准确地说,输入/输出流的相应方法,将某些内容显式写入其 stdin 并从其 stdout 和 stderr 读取由 Process 类的 getInputStream()/getOutputStream()/getErrorStream() 方法返回。如果您想拥有进程而不是线程,这可能是有效的解决方法。

如果你想使用线程,那么它们都共享相同的 stdio。您可以重定向它,但这将毫无意义,因为重定向会影响所有线程。您可以通过使用自定义 InputStream/OutputStream 实现的线程对 IPC 进行某种模仿,或者您可能希望查看 PipedInputStream/PipedOutputStream 对。这些实际上可用于设置 IPC 管道之类的东西,可能与 BufferedInputStream/BufferedOutputStream 结合使用以避免过度阻塞。

于 2011-02-13T17:17:14.683 回答
0

我建议使用单独的进程,或者为每个线程显式分配一个 PrintStream。

但是,即使每个线程看到 System.out 的相同对象,也可以将对 System.out 的写入转发到每个线程的不同位置。在您的启动代码中,您将使用自定义 PrintStream 调用 System.setOut(PrintStream)。这个 PrintStream 将覆盖所有的 print 和 write 方法。在这些方法中,它将使用 InheritableThreadLocal 查找线程的 PrintStream 并将方法调用转发给它。

于 2011-02-13T17:25:51.830 回答