SIGCHILD信号

本文详细解析了SIGCHILD信号的作用与默认处理方式,解释了为何子进程退出时父进程无反应,并提供了自定义SIGCHILD信号处理函数的示例代码,确保父进程能正确处理所有子进程的退出,避免僵尸进程的产生。

SIGCHILD信号,子进程先于父进程退出的话,操作系统通过此信号通知父进程,这个信号的默认处理方式是忽略处理。这就是为什么子进程退出,父进程没有任何反应的原因。
正是父进程对这个信号采用默认的忽略式处理,导致父进程不知道子进程到底什么时候退出,因此导致wait阻塞等待,自定义SIGCHILD,在回调函数中调用waitpid/wait来处理这个子进程。但是SIGCHILD是个非可靠信号,一个父进程可能有很多子进程,如果多个子进程同时退出,信号丢失。也就只处理一个子进程。剩下的子进程也就变成了僵尸进程。
修改回调函数中的代码while(waitpid(-1, NULL, WNOHANG) > 0); 在一次事件中将所能处理的子进程处理完毕。

#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
#include<sys/wait.h>

void handler(int sig)
{
	void(sig);
	pid_t id;
	while((id = waitpid(-1, NULL, WNOHANG)) > 0)
		printf(“wait child success : %d\n”, id);
}

int main()
{
	signal(SIGCHLD, handler);
	pid_t ret = fork();
	if(ret == 0)
	{
		printf(“child : %d\n”, getpid());
		sleep(3);
		exit(0);
	}
	
	while(1)
	{
		printf(“father process is doing some thing!\n”);
		sleep(1);
	}
	return 0;
}
自创守护进程时处理 SIGCHILD 信号并非绝对必要,需依据具体情况判断。 若守护进程会创建子进程,处理 SIGCHILD 信号是必要的。子进程先于父进程退出时,操作系统会通过 SIGCHILD 信号通知父进程,该信号的默认处理方式是忽略。这会导致父进程不知子进程何时退出,wait 会阻塞等待。若不处理此信号,子进程退出后会变成僵尸进程,占用系统资源。例如多个子进程同时退出,因 SIGCHILD 是非可靠信号信号可能丢失,只处理一个子进程,剩下的子进程就会变成僵尸进程。可通过自定义 SIGCHILD 信号处理函数,在回调函数中调用 waitpid 来处理子进程,如以下代码: ```c #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <sys/wait.h> void handler(int sig) { (void)sig; pid_t id; while ((id = waitpid(-1, NULL, WNOHANG)) > 0) printf("wait child success : %d\n", id); } int main() { signal(SIGCHLD, handler); pid_t ret = fork(); if (ret == 0) { printf("child : %d\n", getpid()); sleep(3); exit(0); } while (1) { printf("father process is doing some thing!\n"); sleep(1); } return 0; } ``` 此外,还可采用忽略 SIGCHILD 信号来解决僵尸进程的问题,代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <signal.h> int main() { signal(SIGCHLD, SIG_IGN); pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid == 0) { sleep(3); printf("child\n"); exit(2); } while (1) { printf("father do something\n"); sleep(1); } return 0; } ``` 若守护进程不会创建子进程,就无需处理 SIGCHILD 信号,因为没有子进程退出,也就不会收到 SIGCHILD 信号
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值