当父进程睡眠10秒时,我打算用以下代码派生并执行"sleep 3"作为子进程。我希望父进程在3秒后,即"睡眠3"完成时接收SIGCHLD。
这并没有发生,相反,我得到了:
main
parent process
parent sleeping for 10s
child process
child start, command: /bin/sleep, args: 0x7fffc68c8000, env: 0x7fffc68c8020
ps -ef
显示
chris 10578 10577 0 10:35 pts/25 00:00:00 /bin/sleep 3
后面跟着一个:
chris 10578 10577 0 10:35 pts/25 00:00:00 [sleep] <defunct>
在接下来的七秒钟内(此时父进程退出)。
问题是从未调用过clean_up_child_process
。
我犯了什么错误?
僵尸测试:
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
pid_t child_pid;
sig_atomic_t child_exit_status;
void clean_up_child_process (int signal_number) {
printf("signal receivedn");
/* Clean up the child process. */
int status;
wait (&status);
/* Store its exit status in a global variable. */
child_exit_status = status;
printf("child_exit_status %in", status);
}
int main(int argc, char **argv) {
printf("mainn");
int pid = fork();
if (pid == 0) {
printf("child processn");
signal(SIGCHLD, clean_up_child_process);
char *args[] = { "/bin/sleep", "3", NULL };
char *env[] = { NULL };
printf("child start, command: %s, args: %p, env: %pn", args[0], args, env);
int ret = execve(args[0], args, env);
// if we get here, then the execve has failed
printf("exec of the child process failed %in", ret);
} else if (pid > 0) {
printf("parent processn");
child_pid = pid;
} else {
perror("fork failedn");
}
printf("parent sleeping for 10sn");
sleep(10);
return 0;
}
您告诉子进程等待子进程完成,然后子进程调用execve,它不会创建子进程,而是用您正在执行的程序替换当前程序
您可能希望父级截获子级(即,在执行fork
调用之前进行signal
调用)。
发现:对signal的调用不应该在pid == 0
分支中,因为当调用execve时,该进程将被完全替换。
将信号调用移动到if
之上解决了这个问题。
此行:signal(SIGCHLD, clean_up_child_process);
应在(pid>0)
中写入,而不是(pid == 0)
参见SIGCHLD:
SIGCHLD信号在子进程退出、中断或中断后恢复时被发送给父进程。默认情况下,信号被简单地忽略
因此,父进程收到SIGCHLD,父进程调用clean_up_child_process。