【发布时间】:2015-02-13 08:32:04
【问题描述】:
我正在尝试创建一个生成两个进程的程序——第一个进程监视第二个进程,如果它被杀死则重新启动它。 (想法是杀死第二个进程的唯一方法是首先杀死第一个。)下面我的代码无法实现我的目标。
#include <cstdio>
#include <unistd.h>
#include <thread>
#include <chrono>
#include <signal.h>
#include <cerrno>
void makeSiblings();
void run_ping() {
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(2));
puts("Ping.");
}
}
void run_monitor(pid_t sibling) {
while (kill(sibling, 0) != -1 and errno != ESRCH) {
printf("%d still exists.\n", sibling);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
makeSiblings();
}
void makeSiblings() {
pid_t pid1, pid2;
if ((pid1 = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid1 == 0) {
setsid();
run_ping();
}
if ((pid2 = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid2 == 0) {
setsid();
run_monitor(pid1);
}
}
int main() {
makeSiblings();
}
运行此代码时,它会输出 Ping. 和例如7812 still exists. 分别每两秒和一秒 - 正如预期的那样。然而,当我从另一个终端 kill 7812 时,“Ping”过程激增到一个荒谬的程度——我似乎正在对自己进行分叉轰炸,只有通过发送垃圾邮件 killall 我才能恢复。
我似乎无法理解fork() 或setsid() 的一些微妙之处。我会很感激一两个指针。
【问题讨论】:
-
这显然是 C++,所以我删除了 'C' 标签。
-
它是 C++,是的,但问题是 C 程序员应该可以解决的问题——我用 C++ 编写它的唯一原因是利用 sleep_for() 函数。尽管如此,我还是推迟了。
-
你应该测试
setsid的失败。您应该使用调试器。不要忘记在fork-ing 之前刷新流。尝试strace你的程序。 -
并且监视器应该是被监视程序的父进程。你不能用
SIGKILL来禁止进程被杀死 -
我认为删除C标签是个错误..