如何让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 在发送信号之前就死了。
我想写这样一个函数,从其他地方调用。它使用 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 在发送信号之前就死了。