一、SIGCHLD信号
1. SIGCHLD简介
SIGCHLD的产生条件:
- 子进程终止
- 子进程接收到SIGSTOP信号停止时
- 子进程处于停止状态,接收到SIGCONT后唤醒
注意:通过signal(SIGCHLD, SIG_IGN)通知内核对子进程的结束不关心,由内核回收。如果不想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略SIGCHLD信号,该信号是子进程退出的时候向父进程发送的。
2. 测试代码:
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void sys_err(char* str)
{
perror(str);
exit(1);
}
void do_sig_child(int signo)
{
int status;
pid_t pid;
while ((pid = waitpid(0, &status, WNOHANG)) > 0)
{
if (WIFEXITED(status))
printf("---------------------------child %d exit %d\n", pid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
}
}
int main()
{
pid_t pid;
int i;
for (i = 0; i < 10; i++)
{
if ((pid = fork()) == 0)
break;
else if (pid < 0)
sys_err("fork");
}
if (pid == 0) //子进程
{
int n = 1;
while (n--)
{
printf("child ID %d\n", getpid());
sleep(1);
}
return i + 1;
}
else if (pid > 0) //父进程
{
struct sigaction act;
act.sa_handler = do_sig_child;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD, &act, NULL);
while (1)
{
printf("parent ID %d\n", getpid());
sleep(1);
}
}
return 0;
}
输出结果:

2. 测试代码:
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.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)
{
if (WIFEXITED(status))
printf("---------------------------child %d exit %d\n", pid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
}
}
int main()
{
pid_t pid;
int i;
for (i = 0; i < 10; i++)
{
if ((pid = fork()) == 0)
break;
else if (pid < 0)
sys_err("fork");
}
if (pid == 0) //子进程
{
int n = 1;
while (n--)
{
printf("child ID %d\n", getpid());
sleep(1);
}
return i + 1;
}
else if (pid > 0) //父进程
{
struct sigaction act; //SIGCHLD阻塞
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\n", getpid());
sleep(1);
}
}
return 0;
}
输出结果:

本文深入探讨了Linux系统中SIGCHLD信号的工作原理及其在进程管理中的应用。详细介绍了SIGCHLD信号的产生条件,包括子进程终止、停止或唤醒等场景,并提供了具体的测试代码示例,展示了如何在父进程中捕获并处理SIGCHLD信号,避免僵尸进程的产生。

2182

被折叠的 条评论
为什么被折叠?



