【发布时间】:2014-02-13 18:11:16
【问题描述】:
假设我有一个父进程,它产生很少的工人(子进程)。 我想在其中一个子进程崩溃(被杀死)时得到通知。
获取此通知的最佳方式是什么。 我正在用 c 或 c++ 编程。 我在unix上。并使用 fork_and_exec 产生了 hte 子进程
【问题讨论】:
标签: unix process parent-child pid notify
假设我有一个父进程,它产生很少的工人(子进程)。 我想在其中一个子进程崩溃(被杀死)时得到通知。
获取此通知的最佳方式是什么。 我正在用 c 或 c++ 编程。 我在unix上。并使用 fork_and_exec 产生了 hte 子进程
【问题讨论】:
标签: unix process parent-child pid notify
如果您只想在子进程退出(正常或异常)时收到通知,您可以在父进程中编写一个处理程序来处理 SIGCHLD 信号。每当由此进程产生的进程死亡时,都会执行此处理程序。
但是,您可以在此处理程序中执行的操作存在严重限制。如果收到其他信号,该处理程序将立即中断。即使变量赋值在信号处理程序内部也不是安全操作 - 赋值可能需要两条或更多机器指令,并且它可能被新信号中断,而值未定义。唯一可以在信号处理程序内部安全分配的变量是 sig_atomic_t 类型的变量(保证在一条指令中完成对这种类型变量的分配)。
父进程也必须为子进程“wait”(使用等待功能)——否则,子进程在终止后将成为僵尸。
在我的情况下,这个解决方案就足够了,因为我只需要减少 sig_atomic_t 类型的计数器变量。如果您需要在孩子死亡时进行一些“严肃”处理,则需要其他解决方案。思路可能如下:
C++ 示例可以在下面找到 - 请注意我没有使用线程来等待孩子,但修改示例以使用线程应该不难。
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
int spawn(char* process_name, char** arguments){
pid_t child_id = fork();
if (child_id != 0)
return child_id;
else{
execvp(process_name, arguments);
fprintf(stderr, "An error occured while executing new process.\n");
abort();
}
}
int main(int argc, const char * argv[])
{
char* arguments[] = {
"/Path_to_Child_Exe/Child_Process",
nullptr
};
int i=0;
while (i++ < 10)
spawn((char*) "/Path_to_Child_Exe/Child_Process", arguments);
while (true){
siginfo_t exit_info;
int retVal = waitid(P_ALL, -1, &exit_info, WEXITED);
if (retVal == -1 && errno == ECHILD){
std::cout << "No more children.\n";
break;
}
std::cout << "Child with PID " << exit_info.si_pid << " terminated.\n";
sleep(1);
}
return 0;
}
还需要注意的是,我们在 while 循环的每次迭代结束时调用 sleep。在等待孩子的线程中也应该这样做。否则,如果我们在没有子进程时不暂停地调用 waitid() 函数,CPU 使用率会非常高(我猜是忙等待的一种形式)。因此我们必须时不时调用 sleep 来给 CPU 一个休息的机会。
【讨论】: