【问题标题】:Adapting C fork code to a Java program使 C fork 代码适应 Java 程序
【发布时间】:2014-10-11 22:13:41
【问题描述】:

我正在尝试使用 Java 创建一个小程序来派生两个新的子进程。它是为初学者的编程课准备的,他们的教程是 C它)。

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
pid t pid;

    /*fork a child process*/
    pid = fork();

    if (pid < 0) { /*error occurred*/
        fprintf(stderr, "Fork Failed");
        return 1;
    }
    else if (pid == 0) {/*child process */
        execlp("/bin/ls", "ls", NULL); 
    }
    else { /*parent process*/
        /*parent will wait for the child to complete */
        wait(NULL);
        printf("Child Complete");
    }
    return 0;
}

更新:

我应该为每个子进程及其父进程附加一个 id,在子进程执行时打印信息,并在它终止时打印终止通知。我现在看到上面的这段代码列出了当前目录的内容,并在进程终止时打印“Child Complete”。整个目录的列表是否被视为一个过程?如果是这样,第二个新子进程在哪里/如何出现?

【问题讨论】:

  • 不要使用 C 教程来学习 Java。它在子进程中运行一个名为ls 的命令行实用程序。
  • @ElliotFrisch 我希望我不必这样做,但正如我提到的那样,这是为了学校。
  • 我认为这个答案非常接近您的期望:stackoverflow.com/a/5437863/51760
  • @Aif 我看到了这篇文章,但想知道这是运行多个进程还是只是多个线程?

标签: java c


【解决方案1】:

好吧,回答一下程序的作用:

当 fork() 执行时,你会得到两个进程。 它们做的事情完全相同,只是其中一个(孩子)从 fork() 返回 0,而父母从 fork() 获得任何其他正值。 fork() 的负返回意味着它失败了。

因此,通过查看 fork() 的返回值,该进程可以确定它是子进程还是父进程。 在您的情况下,您让孩子执行“ls”命令,该命令列出当前目录中的文件。

您让父进程 wait() 等待其所有子进程完成。然后你说“孩子完成”。

您可以尝试删除 wait() 系统调用,以更清楚地看到两个进程实际上是同时运行的。 查看 ps(1)、ls(1)、fork(2) 和 exec(3) 的手册页。

【讨论】:

  • 这让我更好地了解给定代码示例的作用。但是,对于我在上面的更新中添加的一点,我仍然有些困惑。
  • 是的,目录列表是一个单独的过程。当你 fork() 时,操作系统会启动一个新进程,该进程执行与父进程相同的二进制文件。您可以从 getpid() 打印出值,以真正看到它们具有不同的进程 ID:s!但请注意,您的 execlp() 调用将“重载”子进程。
【解决方案2】:

在 Java 中,这可能类似于 -

public static void main(String[] args) {
    try {
        Process p = Runtime.getRuntime().exec("/bin/ls");
        final InputStream is = p.getInputStream();
        Thread t = new Thread(new Runnable() {
            public void run() {
                InputStreamReader isr = new InputStreamReader(is);
                int ch;
                try {
                    while ((ch = isr.read()) != -1) {
                        System.out.print((char) ch);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        p.waitFor();
        t.join();
        System.out.println("Child Complete");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

【讨论】:

  • 添加 import java.io.InputStream 后效果很好;导入 java.io.InputStreamReader;导入 java.io.IOException;就像提到的其他答案一样,这打印了当前目录的内容。这被认为是一个子进程吗?我更新了我的问题。
  • @user25976 是的。 /bin/ls 是一个子进程。还有一个线程正在运行以处理该进程的输出。
猜你喜欢
  • 2020-12-12
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多