我打算将以下代码作为子进行fork和exec“sleep 3”,同时父进程休眠10秒。我希望父进程在3s之后接收SIGCHLD,当“sleep 3”完成时。
这不会发生,而是我得到:
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
。
我犯了什么错误?
zombietest.c:
#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 received\n");
/* 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 %i\n", status);
}
int main(int argc, char **argv) {
printf("main\n");
int pid = fork();
if (pid == 0) {
printf("child process\n");
signal(SIGCHLD, clean_up_child_process);
char *args[] = { "/bin/sleep", "3", NULL };
char *env[] = { NULL };
printf("child start, command: %s, args: %p, env: %p\n", 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 %i\n", ret);
} else if (pid > 0) {
printf("parent process\n");
child_pid = pid;
} else {
perror("fork failed\n");
}
printf("parent sleeping for 10s\n");
sleep(10);
return 0;
}
答案 0 :(得分:2)
您告诉孩子等待子进程完成,然后子进程调用execve,它不会创建子进程,而是将当前程序替换为您正在执行的程序
您可能希望家长拦截孩子(即在执行signal
电话之前进行fork
通话)。
答案 1 :(得分:0)
找到它:对信号的调用不应该在pid == 0
分支中,因为在调用execve时该过程完全被替换。
将信号调用移到if
上方可以解决问题。
答案 2 :(得分:0)
这一行:signal(SIGCHLD, clean_up_child_process);
应该在(pid>0)
而不是(pid == 0)
中写入
{{1}}
见SIGCHLD:
当 SIGCHLD 信号在中断后退出,中断或恢复时,信号被发送到子进程的父。默认情况下,信号被忽略。
因此,父进程收到了SIGCHLD,父进程调用了clean_up_child_process。