linux系统编程之进程信号的使用

博客介绍了信号捕捉特性,如进程正常运行和信号捕捉函数执行时屏蔽信号的规则,阻塞常规信号不支持排队。还阐述了SIGCHLD信号,子进程暂停或退出时会发送该信号,可通过捕捉它回收子进程,同时说明了信号注册时间及处理时屏蔽和解除屏蔽信号的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提介绍

信号捕捉特性:
   1. 进程正常运行时,默认pcb中有一个信号屏蔽字,假定为*,它决定了进程自动屏蔽哪些信号,当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数,而该函数有可能执行很长时间,在这期间所屏蔽的信号不由来指定,而是用sa_mask来指定,调完信号处理函数,再次恢复
   2. xxx信号捕捉函数执行期间,xxx信号自动被屏蔽
   3. 阻塞的常规信号不支持排队,产生多次只记录一次。(即前31个)


SIGCHLD信号
  子进程在暂停或者退出的时候回发送SIGCHLD信号,可以通过捕捉SIGCHLD
信号来回收子进程。

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

void catch_sig(int num){
	pid_t wpid;
	while( (wpid = waitpid(-1,NULL,WNOHANG)) > 0){
		printf("wait child %d ok\n",wpid);
	}
}

int main(){
	int i =0;
	pid_t pid;
	//在创建子进程之前屏蔽SIGCHLD信号
	sigset_t myset,oldset;
	sigemptyset(&myset);
	sigaddset(&myset,SIGCHLD);
	sigprocmask(SIG_BLOCK,&myset,&oldset);
	for(i = 0; i< 10; i++){
		pid = fork();
		if(pid == 0){
			break;
		}
	}
	if(i == 10){
		struct sigaction act;
		act.sa_flags = 0;
		sigemptyset(&act.sa_mask);
		act.sa_handler = catch_sig;
		sigaction(SIGCHLD,&act,NULL);
		//解除屏蔽信号
		sigprocmask(SIG_SETMASK,&oldset,NULL);
		while(1){
			sleep(1);
		}
	}
	else if(i <  10){
		printf("i am %d child, pid = %d\n",i,getpid());
		//sleep(i);
	}
}
  1. 信号执行函数,回收子进程,可以用循环,一次会回收多个,不需要每个进程结束都触发信号,从信号处理函数中回收,这样每次只能回收一个。

  2. SIGCHLD信号的注册一定要在进程创建之前(或者在进程结束之前完成)完成。(否则会出现进程已经结束,信号没有捕捉到,即僵尸进程)
    处理:
    可以在创建子进程之前屏蔽SIGCHLD信号
     sigset_t myset,oldset;
     sigemptyset(&myset);/清空
     sigaddset(&myset,SIGCHLD);
     sigprocmask(SIG_BLOCK,&myset,&oldset);//oldset 保留现场,设置了SIGHLD到阻塞信号集。
    注册信号之后,需要解除屏蔽现场:
     sigpromask(SIG_SETMASK,&oldset,NULL);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值