我怎样才能让孩子等待父母返回(而不是退出)然后自杀



我想写这样一个函数,它可以从其他地方调用。使用fork生成子进程并等待主进程返回其主函数。我尝试了这个方法,也尝试了设置一面旗帜来告诉孩子父母回来了。但他们都不正确,我知道原因。我只是想知道我该如何证明这一点?谢谢!

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

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

假设父进程没有终止,则必须手动向子进程发送信号。

设置方法如下:

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

现在你的子进程得到了父进程"死亡"的信号。

如果你不需要任何额外的处理,但只是子终止你可以"跳过"自定义信号处理和发送SIGTERM而不是SIGUSR1。默认情况下,这将结束进程。


你应该阅读一些关于信号的内容,这将有助于你更好地理解代码。

你说你想让孩子

等待主进程返回其主函数

。这有点难以理解,但我认为您的意思是希望子进程等待,直到它的父进程返回到执行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 %dn", (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
    }
}

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

相关内容

最新更新