如何让孩子等待父母返回(不退出)然后自杀?

时间:2016-10-07 13:25:21

标签: c fork glibc

我想写一个从其他地方调用的函数。使用fork来生成子进程并等待主进程返回其主函数。我尝试了这种方法,并试图设置一个标志告诉孩子父母返回。但他们都不正确,我知道原因。我只是想知道如何才能说明这一点?谢谢!

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;
}
}

2 个答案:

答案 0 :(得分:1)

你说你想让孩子

  

等待主进程返回其主函数

。这有点难以理解,但我认为你的意思是你希望孩子等到其进程返回到其中的调用者的函数fork()已完成。目前还不清楚调用者是否应该是该过程的main()功能,但这实际上并没有任何区别。

但是,没有任何功能可以直接控制返回时发生的事情。它能做的最好就是在它返回之前立即执行一些操作。

此外,由于您提供的函数不是main(),因此没有理由假设父进程从该函数返回时终止。在它终止之前,子进程仍然是它的子进程,因此不会观察到进程1继承的进程。

由于程序实际上没有按预期工作,我认为父进程确实没有终止,所以你需要一个不同的方法。具体而言,您需要某种形式或其他进程间通信(IPC)。有几种口味可供选择,作为奖励,其中许多不需要孩子忙等待。其中更有可能的选择是

  • 进程共享的互斥锁或信号量
  • 一个信号
  • 管道

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

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
    }
}

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

答案 1 :(得分:0)

假设您的父进程未终止,您必须手动向孩子发送信号。

以下是如何进行设置:

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命令不会杀死孩子,但会向其发送信号(名称可能会产生误导)。

当您的父母终止时,虽然您不需要手动发送信号,但可以告诉Linux在父母去世时向您发送信号。

这可以通过添加

来完成
prctl(PR_SET_PDEATHSIG, SIGUSR1);

现在,您的子进程会收到关于&#34; death&#34;父母的。

如果您不需要任何额外的处理,但只是孩子要终止,您可以跳过&#34;跳过&#34;自定义信号处理并发送SIGTERM而不是SIGUSR1。默认情况下,这将结束该过程。

您应该阅读有关信号,这将有助于更多地理解代码。