signal函数-进程对信号的响应

1.signal函数

#include <signal.h>

void (*signal(int signo, void (*func)(int)))(int);

返回:若成功则返回先前的信号处理函数指针,出错则返回SIG_ERR;

功能:向内核登记信号处理函数;

参数:signo:要登记的信号值

     func:a.信号处理函数指针;b.SIG_IGN,忽略信号;c.SIG_DFL,采用系统默认的方式处理信号,执行默认操作


2.进程对信号的三种响应

下面以SIGINT信号为例,对这三种响应方式进行说明。

(1)忽略信号,signal(SIGINT,SIG_IGN);

SIG_IGN代表忽略SIGINT信号,SIGINT信号代表由InterruptKey产生,通常是Ctrl+C或者是DELETE。发送给所有ForeGround Group的进程。

下面我们写个死循环:

#include <stdio.h>
#include <signal.h>
int main(void)
{
     signal(SIGINT, SIG_IGN);
     for(;;);
     return 0;
}
这时我们保存执行,按下Ctrl+C程序没有反应,这就对了。

如果我们想结束该程序可以按下Ctrl+\来结束

其实当我们按下Ctrl+\组合键时,是产生了SIGQUIT信号。


(2)执行默认操作,signal(SIGINT, SIG_DFL)

SIG_DFL代表执行系统默认操作,其实对于大多数信号的系统默认动作是终止改进程,与不写此处理函数的效果是一样的。

#include <stdio.h>
#include <signal.h>
int main(void)
{
     signal(SIGINT, SIG_DFL);
     for(;;);
     return 0;
}
这时就可以按下Ctrl+C来终止该进程了。把signal(SIGINT, SIG_DFL)这句去掉,效果是一样的。


(3)捕获信号,signal(SIGINT, sig_handler);

#include <stdio.h>
#include <signal.h>

void sig_handler(int signo)
{
     printf("catch the signal:%d", signo);
}

int main(void)
{
     // 登记一下SIGINT信号
     if(signal(SIGINT, sig_handler) == ERR)
     printf("signal error");
     for(;;);

     return 0;
}
这种情况下,当按下Ctrl+C时,会执行我们定义的信号处理函数。

想要退出,可以按下Ctrl+\


3.对信号处理的几点说明

(1) SIGKILL和SIGSTOP这两个信号永远不能忽略;

(2) SIGKILL和SIGSTOP不能被捕获(即使已经登记了,也不能被捕获);

(3) 进程启动时SIGUSR1和SIGUSR2两个信号被忽略;


4.几个常见的信号

(1)SIGINT,编号为2,相当于执行Ctrl+C;

(2)SIGTSTP,编号为20,相当于Ctrl+Z,暂停一个进程;

(3)SIGCONT,编号为18,继续执行被暂停的信号,格式为:kill -SIGCONT/18 进程ID

(4)SIGCHLD,编号为17,子进程结束产生该信号;(信号的异步处理表现在:当SIGCHLD产生时,父进程对其捕获处理,其他时间父进程该干嘛干嘛)

下面举例来说明SIGCHLD信号的用法。

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

void sig_handler(int signo)
{
	printf("child process deaded, signo: %d\n", signo);
	wait(0);// 当捕获到SIGCHLD信号,父进程调用wait回收,避免子进程成为僵尸进程
}

void out(int n)
{
	int i;
	for(i = 0; i < n; ++i)
	{
		printf("%d out %d\n", getpid(), i);
		sleep(2);
	}
}

int main(void)
{
	// 登记一下SIGCHLD信号
	if(signal(SIGCHLD, sig_handler) == SIG_ERR)
	{
		perror("signal sigchld error");
	}
	pid_t pid = fork();
	if(pid < 0)
	{
		perror("fork error");
		exit(1);
	}
	else if(pid > 0)
	{
		// parent process
		out(100);
	}
	else
	{
		// child process
		out(10);
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值