使用fork()创建“后台运行”的孩子并用信号杀死他们每个人
我需要创建n来自同一父母的孩子,并让他们运行,同时父母无限地询问要发送给某个孩子的信号。我让父母创建那些儿童,但他们完成了执行,所以我让他们进入一段时间(1)循环。问题是,当我试图杀死任何一个孩子时,它变成了一个僵尸进程,而不是实际终止它的执行。我猜这是因为父母仍在等待孩子终止执行,他们不会发送退出状态。所以...首先,我真的需要让孩子进入一个无限的while循环,让他们在父母询问信号时运行吗?如果我这样做,我该如何避免这种“永不终止执行”的问题?我需要找到一种让孩子们退出while循环的方式,并发送实际的“完成执行”信号,因为我认为我不能使用wait()
,因为孩子们从未真正完成跑步,他们只是由父母终止。使用fork()创建“后台运行”的孩子并用信号杀死他们每个人
谢谢。 PS:在Linux中运行。这是我的代码
int main(){
int i;
pid_t parent = getpid();
pid_t pid[4];
printf("parent with pid %d\n", parent);
for(i = 0; i < 5; i++){
pid[i] = fork();
if(pid[i] < 0){
perror("Error in fork.");
exit(1);
} else if(pid[i] == 0 && getppid() == padre) {
printf("Number: %d pid %d, parent: %d\n", i, getpid(), getppid());
while(1);
}
}
if(getpid() == padre){
while(1){
printf("Enter pid and signal:\n");
int x, y;
scanf("%d", &x); // pid
scanf("%d", &y); // signal
printf("you did: kill(%d, %d)\n", x, y);
kill(x, y);
}
}
return 0;
}
编辑: 最终代码的答案来实现:https://github.com/sebasura/sistope
的问题是,当我试图杀死任何一个孩子,就变成了僵尸进程,而不是实际终止它的执行。
嗯,是的,没有。成为僵尸通常是当进程终止时发生的,直到该进程被父进程收集为止。一个僵尸在进程表中占用一点空间,但它不是运行,因此不消耗CPU。
我猜这是因为父母仍在等待孩子终止执行,他们不会发送退出状态。
不,这是因为kill()
只是发送一个信号。您需要使用wait()
函数之一 - 也许是waitpid()
- 才能真正收集终止的孩子。
所以......首先,我真的需要让孩子进入一个无限的while循环,让他们在父母询问信号时运行吗?
号的孩子可以使用sigwait()
或其变体的一个等待信号从一组指定,或pause()
中止执行待收到终止处理或触发信号处理函数的任何信号。但是,请注意,有些信号默认不含这两种信号,因此sigwait()
可能是更好的选择。
如果我这样做,我该如何避免这种“永不终止执行”的问题?
孩子必须因接收信号而终止。这已经发生在你身上,因为孩子们正在变成僵尸。使用你现在的代码,它可能取决于你发送了哪个信号,但是,有些人的默认处理不会终止进程。
好吧,我需要做的是:在while(1)循环中取出while(1),并用pause()或sigwait()取代它,然后在kill()后收集带有waitpid()对?我不知道如何使用sigwait(),我有点用waitpid()丢失。我需要使用的唯一信号是SIGUSR1,SIGUSR2和SIGTERM,所以我认为pause()会很好。我试着用waitpid(x,&state,WNOHANG | WUNTRACED)收集孩子;但它对僵尸孩子毫无意义。我真的不知道如何实现这些变化,因为我没有完全理解函数v_v。 – Sebasuraa
@Sebasuraa,是的,除了绝对不使用'WNOHANG',并且可能不使用'WUNTRACED'。前者特别会引入竞争条件 - 如果它在父节点的waitpid()'调用之前恰好结束,则会收集子节点,否则不会。如果必要的话,父母没有比等待孩子终止任何事情更好的了,所以这就是它应该做的。 –
谢谢大家,我做到了。我使用pause()
而不是while(1)
。
与毁伤后,我用这个:
int state;
waitpid(pid, &state, 0);
这是一门功课的一部分,所以我会在到期日之后上传的代码,使他们不惩罚我要分享它或东西。
再次感谢。 编辑: 下面是最终代码https://github.com/sebasura/sistope
读取有关['wait'](http://man7.org/linux/man-pages/man2/wait.2.html)系统调用,并且它兄妹。 –
杀死后的'waitpid()'调用将是一个好的开始。 – mshildt
而不是'while(1);',你可能更喜欢'暂停()'。 –