【问题标题】:Create independent process in Linux在 Linux 中创建独立进程
【发布时间】:2015-07-23 20:57:30
【问题描述】:

我希望在 Linux 上实现类似于 CreateProcess 的功能。我做了很多研究,发现"Fork off and die" 方法使用双叉子在init 下运行子进程。也就是让孩子独立于父母操作。

因为父进程需要返回有关新创建的子进程的信息(即 pid、名称等),所以我需要知道我的代码中是否遇到了竞争条件。目前,我通过管道 fork 并检索第二个 fork 的 pid,然后等待第一个 fork 退出。

int child = 0;
int fd[2] = { 0, 0 };

if (pipe (fd) != 0)
    return Process();

int pid = fork();
if (pid < 0)
    return Process();

if (pid == 0) // Child
{
    if (setsid() != -1)
    {
        child = fork();
        if (child == 0)
        {
            umask (0); // Reset umask
            close (0); // Close stdin
            close (1); // Close stdout
            close (2); // Close stderr

            execvp ( ... );
            _exit (0);
        }

        // Do I need waitpid (child) here?
    }

    // Write the child PID using the pipe
    write (fd[1], &child, sizeof (child));
    _exit (0);
}

else // Parent
{
    // Read the child PID using the pipe
    read (fd[0], &child, sizeof (child));

    // Remove zombie process
    waitpid (pid, nullptr, 0);

    // Child must finish exec by this point

    return Process (child);
        // Also gets name
}

问题:

  • 是否需要第二个 waitpid 来等待子进程完成 exec?
  • waitpid 是否在调用 exec 时返回?
  • 即使在 waitpid 之前调用了 exit 或 exec,waitpid 是否会返回?

【问题讨论】:

  • 为什么要双叉?当新进程不应该是原始进程的子进程时,就会执行双分叉,这与您想要做的完全相反。
  • 这正是我想做的。我想创建一个与父进程无关的进程。因此,即使父母去世,孩子也会继续。我返回孩子的 PID,以便以后可以根据需要对其进行调试。这就是 CreateProcess 函数在 Windows 上的作用,我需要在 Linux 上复制它。
  • 在双分叉方法中,新进程不是原始进程的子进程。你不能一边吃蛋糕一边吃,除非你以一种可怕的方式破解某些东西。
  • 为什么要创建一个不是原始进程子进程的进程?
  • 我知道这不是个孩子。我不希望它成为一个孩子,我希望它独立,摆脱 Init。我在这里启动一个守护进程。这个新进程就像任何其他进程一样,我将能够像任何远程进程一样“附加”到它。这是我在这里构建的一个远程过程分析库。

标签: c++ linux process fork posix


【解决方案1】:

第二个孩子不需要waitpid()。当一个进程的父进程死亡时,子进程将被init进程收养,所以不会有僵尸进程。

waitpid() 仅在它等待退出的子进程后返回。在子进程中调用execvp() 意味着服务员会一直等到执行的程序终止,因为那是子进程死亡的时间。

waitpid() 将获取进程的退出状态。进程何时真正退出并不重要。

【讨论】:

  • 但是对于当前的代码,我理解的方式是返回的进程有可能在调用 exec 之前(或期间)执行。我需要保证 waitpid 仅在 exec 结束时返回。
  • 如果你想等待孩子的execvp()完成,不要做双重fork()
【解决方案2】:

(稍微澄清一下:您所说的孩子,实际上是您的孙子。它是刚刚分叉并死亡的进程的孩子。)

我是否需要第二个 waitpid 来等待孩子完成执行?

你不能。这是你的孙子,你只能等待你的直系子女。此外,由于您孙子的父母已经去世,您的孙子现在已经重新成为 init 的父母(所以它实际上是您的前孙子)。

waitpid 是否会在调用 exec 时返回?

Waitpid 在给定 pid 死亡/退出时返回,或者如果它已经是僵尸则立即返回。 exec 在孙子中被调用。您的 waitpid 调用根本不关心不是您的直接子进程的进程(除非您使用的是 Linux-only child-subreaper 功能)。

即使在 waitpid 之前调用了 exit 或 exec,waitpid 是否也会返回?

Waitpid 仅在等待的 pid(必须是您的直接子代)死亡时才返回。如果还不是这种情况,它将阻塞。

【讨论】:

  • 确实我不能在孙子上调用 waitpid,但是如果你看一下代码,我的第二个 waitpid 就在第二个分叉之后。也就是说,孩子会在孙子身上等待,但你说 exec 不会触发它。还有比赛条件呢。如果返回的 Process 在 exec 调用之前被执行怎么办?
  • 如果你仍然关心你的孙子,因为你想等待它并且有一个可靠的*参考,你应该把它变成你的孩子,而不是通过双重分叉拒绝它。 (*除非具有特定 pid 的进程是您的孩子,否则您不能将该 pid 用作对其的可靠引用,因为进程来来去去,它们的 pid 会被回收)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-18
  • 2011-06-22
  • 2015-01-07
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多