如何让child等待parents到return(不退出)然后自杀?

How can I make child waiting parents to return (not exit) and then suicide?

我想写这样一个函数,从其他地方调用。它使用 fork 来创建一个 child 并等待主进程到 return 到它的主要功能。我尝试了这个方法,也尝试设置一个标志来告诉child parents return。但他们都不正确,我知道原因。我只想知道我怎样才能说明这一点?谢谢!

void otherplacecall(){
fpid=fork();
if (fpid == 0) {
    printf("i am the child process, my process id is %d\n",getpid());
    while(getppid()!=1){printf("waiting\n");sleep(1);}
    if(getppid()==1){
        printf("father die!\n");
        printf("I am dying\n");
        exit(0);
        }
    }


else {
    printf("in the parents!, my process id is%d\n",getpid());
    printf("my son take care of yourself\n");
    return 1;
}
}

假设您的 parent 进程 没有终止 ,您必须手动向 child 发送信号。

设置方法如下:

int run = 1;
void OnSigUsr1()
{
    run = 0;
}

///....
signal(SIGUSR1, OnSigUsr1);
pid = fork();
if(pid == 0)
{ //we are the child
    //loop until SIGUSR1 comes in
    while(run == 1) p_sleep(1000);
}
else
{ //we are the parent
    //send the SIGUSR1 signal to child
    kill(pid,SIGUSR1);
}

当进程现在获得信号 SIGUSR1 时,函数 OnSigUsr1 被调用。在此您可以将一些全局变量设置为 false。

kill 命令不会杀死 child 但会向它发送信号(名称可能会产生误导)。

当你的 parent 自己 终止 虽然你不需要手动发送信号但可以告诉 Linux 向你发送信号当 parent 死亡时。

这可以通过添加

来完成
prctl(PR_SET_PDEATHSIG, SIGUSR1);

现在您的 child 进程在 parent 的 "death" 上获得信号。

如果您不需要任何额外的处理而只需要 child 来终止您可以 "skip" 自定义信号处理并发送 SIGTERM 而不是 SIGUSR1。默认情况下,这将结束进程。


您应该稍微阅读一下信号,这将有助于更好地理解代码。

你说你想要 child 到

wait main process to return to its main function

。这有点难以理解,但我认为你的意思是你希望 child 等到它的 parent 过程 returns 到 执行 fork() 的函数的调用者。目前还不清楚调用者是否应该是该进程的 main() 函数,但这实际上没有任何区别。

但是,没有函数可以直接控制它 returns 时发生的事情。它能做的最好的事情就是在它之前立即执行一些操作 returns.

此外,由于您提供的函数不是 main(),因此没有理由假设 parent 进程在从该函数 returns 时终止。在它确实终止之前​​,child 进程将保持其 child,因此不会观察到自己被进程 1 继承。

由于程序实际上并没有像您预期的那样工作,我想 parent 进程确实没有终止,因此您需要一种不同的方法。具体来说,您需要某种形式或其他 inter-process 通信 (IPC)。有多种口味可供选择,作为奖励,其中许多不需要 child 到 busy-wait。更有可能的选择是

  • a process-shared 互斥量或信号量
  • 一个信号
  • 一根烟斗

其中,我推荐最后一个。它可能看起来像这样:

void otherplacecall(){
    int pfd[2];
    pid_t pid;
    char c;

    if (pipe(pfd)) {
        // ... handle error in pipe() ...
        return;
    }
    switch(pid = fork()) {
        case -1:
            // (parent) ... handle error in fork() ...
            break;

        case 0:
            // child
            printf("child: my process id is %d\n", (int) pid);
            if (close(pfd[1])) {
                // ... handle error in close() ...
                _Exit(1);
            }
            if (read(pfd[0], &c, 1) < 0) {
                // ... handle error in read() ...
            }
            puts("child: received the signal to proceed");
            puts("child: I terminating");
            _Exit(0);

        default:
            // parent
            close(pfd[0]);
            puts("parent: my son, take care of yourself");
            close(pfd[1]);  // this will cause the child's read() to return
    }
}

这种方法的特点之一是,如果 parent 确实 终止,那么它的管道末端副本将被关闭,即使它没有关闭它们明确地,所以 child 将继续。在某些其他情况下不会发生这种情况,例如 child 正在等待信号,而 parent 在发送信号之前就死了。