C++ 在Linux中创建独立进程

C++ 在Linux中创建独立进程,c++,linux,process,fork,posix,C++,Linux,Process,Fork,Posix,我希望在Linux上实现一个类似于but的功能。我做了很多研究,发现了一种使用双叉在init下运行孩子的方法。也就是说,允许子系统独立于父系统运行 因为父进程需要返回有关新创建的子进程的信息(即pid、名称等),所以我需要知道我的代码中是否遇到竞争条件。目前,我分叉并通过管道检索第二个分叉的pid,然后等待第一个分叉退出 int child = 0; int fd[2] = { 0, 0 }; if (pipe (fd) != 0) return Process(); int pid

我希望在Linux上实现一个类似于but的功能。我做了很多研究,发现了一种使用双叉在init下运行孩子的方法。也就是说,允许子系统独立于父系统运行

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

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
}
int child=0;
int fd[2]={0,0};
如果(管道(fd)!=0)
返回过程();
int-pid=fork();
if(pid<0)
返回过程();
if(pid==0)//子级
{
如果(设置ID()!=-1)
{
child=fork();
如果(子项==0)
{
umask(0);//重置umask
close(0);//关闭stdin
关闭(1);//关闭标准输出
关闭(2);//关闭stderr
execvp(…);
_出口(0);
}
//我需要孩子在这里吗?
}
//使用管道编写子PID
写入(fd[1],&child,sizeof(child));
_出口(0);
}
else//Parent
{
//使用管道读取子PID
读取(fd[0],&child,sizeof(child));
//移除僵尸进程
waitpid(pid,nullptr,0);
//子级必须在此点完成exec
返回过程(子级);
//也得到名字
}
问题:

  • 我是否需要第二个等待PID来等待孩子完成执行
  • waitpid是否在调用exec时返回
  • 即使在waitpid之前调用exit或exec,waitpid是否返回

您不需要对第二个子项执行
waitpid()
。当一个进程的父进程死亡时,子进程将被
init
进程采用,因此不会有僵尸进程

waitpid()
仅在等待的子级退出后返回。在子对象中调用
execvp()
意味着服务生将等待执行的程序死亡,因为此时子对象将死亡

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

(有一点澄清:你所称的孩子实际上是你的孙辈。是进程的孩子刚刚分叉并死亡。)

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

你不能。是你的孙子,你只能照顾你的直系子女。此外,由于您孙辈的父母已经去世,您的孙辈现在已被重新租给init(因此它实际上是您的前孙辈)

waitpid是否在调用exec时返回

Waitpid在给定pid死亡/退出时返回,如果它已经是僵尸,则立即返回。执行官在孙辈中被召来。您的waitpid调用与非直接子进程无关(除非您使用的是Linux独生子subreaper特性)

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


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

确实,我不能对孙子调用waitpid,但是如果您查看代码,我的第二个waitpid就在第二个fork之后。也就是说,孩子会等孙子,但你是说exec不会触发。还有比赛条件呢。如果返回的进程在exec调用之前被执行了怎么办?如果你仍然关心你的孙子,因为你想等待它,并且对它有一个可靠的*引用,那么你应该让它成为你的孩子,而不是通过双重分叉来否认它。(*除非具有特定pid的进程是您的子进程,否则您不能将该pid用作可靠的引用,因为进程来来去去,它们的pid得到回收)。但就当前代码而言,我的理解是,返回的进程有可能在调用exec之前(或期间)执行。我需要保证waitpid仅在exec结束时返回。如果要等待子级的
execvp()
完成,请不要执行double
fork()
。为什么要执行double
fork?当新流程不应该是原始流程的子流程时,就会进行双重分叉,这与您想要做的正好相反。这正是我想要做的。我想创建一个与父进程无关的进程。因此,即使父母去世,孩子也会继续。我返回孩子的PID,以便以后可以调试它。这就是CreateProcess函数在Windows上所做的,我需要在Linux上复制它。在双分叉方法中,新进程不是原始进程的子进程。除非你以一种可怕的方式进行黑客攻击,否则你不能既吃蛋糕又吃蛋糕。你为什么要创建一个不是原始流程的子流程?我知道它不是子流程。我不希望它是一个孩子,我希望它是独立的,从初始运行。我在这里启动一个守护进程。这个新进程将与任何其他进程一样,我将能够像连接任何远程进程一样“连接”到它。这是我在这里建立的一个远程过程分析库。