linux的SIGCHLD信号
SIGCHLD的产生条件
子进程终止时
子进程接收到SIGSTOP信号停止时
子进程处在停止态,接受到SIGCONT后唤醒时
借助SIGCHLD信号回收子进程
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> void sys_err(char *str) { perror(str); exit(1); } void do_sig_child(int signo) { int status; pid_t pid; // if ((pid = waitpid(0, &status, WNOHANG)) > 0) { while ((pid = waitpid(0, &status, WNOHANG)) > 0) { if (WIFEXITED(status)) printf("------------child %d exit %d ", pid, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("child %d cancel signal %d ", pid, WTERMSIG(status)); } } int main(void) { pid_t pid; int i; //阻塞SIGCHLD for (i = 0; i < 10; i++) { if ((pid = fork()) == 0) break; else if (pid < 0) sys_err("fork"); } if (pid == 0) { //10个子进程 int n = 1; while (n--) { printf("child ID %d ", getpid()); sleep(1); } return i+1; } else if (pid > 0) { //SIGCHLD阻塞 struct sigaction act; act.sa_handler = do_sig_child; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGCHLD, &act, NULL); //解除对SIGCHLD的阻塞 while (1) { printf("Parent ID %d ", getpid()); sleep(1); } } return 0; }
分析该例子。结合 17)SIGCHLD 信号默认动作,掌握父使用捕捉函数回收子进程的方式。 【sigchild.c】
如果每创建一个子进程后不使用sleep可以吗?可不可以将程序中,捕捉函数内部的while替换为if?为什么?
if ((pid = waitpid(0, &status, WNOHANG)) > 0) { ... }
思考:信号不支持排队,当正在执行SIGCHLD捕捉函数时,再过来一个或多个SIGCHLD信号怎么办?
子进程结束status处理方式
pid_t waitpid(pid_t pid, int *status, int options)
options
WNOHANG
没有子进程结束,立即返回
WUNTRACED
如果子进程由于被停止产生的SIGCHLD,waitpid则立即返回
WCONTINUED
如果子进程由于被SIGCONT唤醒而产生的SIGCHLD,waitpid则立即返回
获取status
WIFEXITED(status)
子进程正常exit终止,返回真
WEXITSTATUS(status)返回子进程正常退出值
WIFSIGNALED(status)
子进程被信号终止,返回真
WTERMSIG(status)返回终止子进程的信号值
WIFSTOPPED(status)
子进程被停止,返回真
WSTOPSIG(status)返回停止子进程的信号值
WIFCONTINUED(status)
SIGCHLD信号注意问题
1. 子进程继承了父进程的信号屏蔽字和信号处理动作,但子进程没有继承未决信号集spending。
2. 注意注册信号捕捉函数的位置。
3. 应该在fork之前,阻塞SIGCHLD信号。注册完捕捉函数后解除阻塞。
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇: java的Collection类详解
- 下一篇:没有了