#include <sys/types.h> /* 在任何其它 sys 下的头文件之前引用这个头文件 */
#include <sys/wait.h> /* waitpid()和一些不同的宏所需的头文件 */
#include <signal.h> /* 信号函数的头文件 */
#include <stdio.h> /* fprintf函数的头文件 */
#include <unistd.h> /* fork函数的头文件 */
void sig_chld(int); /* 我们的 SIGCHLD 信号处理函数的原形(prototype) */
int main()
{
struct sigaction act;
pid_t pid;
/* 设定sig_chld函数作为我们SIGCHLD信号的处理函数 */
act.sa_handler = sig_chld;
/* 在这个范例程序里,我们不想阻塞其它信号 */
sigemptyset(&act.sa_mask);
/*
* 我们只关心被终止的子进程,而不是被中断
* 的子进程 (比如用户在终端上按Control-Z)
*/
act.sa_flags = SA_NOCLDSTOP;
/*
* 使这些设定的值生效. 如果我们是写一个真实的应用程序,
* 我们也许应该保存这些原有值,而不是传递一个NULL。
*/
if (sigaction(SIGCHLD, &act, NULL) < 0)
{
fprintf(stderr, "sigaction failed\n");
return 1;
}
/* fork */
switch (pid = fork())
{
case -1:
fprintf(stderr, "fork failed\n");
return 1;
case 0: /* 是子进程,直接结束 */
_exit(7); /* 退出状态 = 7 */
default: /* 父进程 */
sleep(10); /* 给子进程完成的时间 */
}
return 0;
}
/*
* 信号处理函数 -- 只有当接收到一个SIGCHLD信号才被调用,
* 即有一个子进程终止
*/
void sig_chld(int signo)
{
int status, child_val;
/* 非阻塞地等待任何子进程结束 */
if (waitpid(-1, &status, WNOHANG) < 0)
{
/*
* 不建议在信号处理函数中调用标准输入/输出函数,
* 但在一个类似这个的玩具程序里或许没问题
*/
fprintf(stderr, "waitpid failed\n");
return;
}
/*
* 我们现在有保存在‘status’变量中的子进程退出信息并可以使用
* wait.h中定义的宏对其进行操作
*/
if (WIFEXITED(status)) /* 子进程是正常退出吗? */
{
child_val = WEXITSTATUS(status); /* 获取子进程的退出状态 */
printf("child's exited normally with status %d\n", child_val);
}
}