Linux程序退出信号和其他信号捕获处理

一、前言

  信号是一种软件中断(软中断信号),用来通知进程发生了异步事件。在Linux下进程之间可以互相通过系统调用kill发送软中断信号。
  一般情况下,对信号的处理可以分为三大类:

1、进程指定信号的处理函数,当接收到该信号时由指定的函数进行处理。
2、忽略信号,即进程接收到信号不做任何处理。
3、由系统默认处理信号,对大部分的信号的缺省操作是使得进程终止。

  在实际的应用开发中,可能需要对某些信号进行捕获并自定义处理方法,尤其是系统默认使进程退出的信号,因为有时候需要在程序正常退出或异常退出之前完成某些处理工作,保证程序的可靠性。
  因此,我们需要捕获使得程序退出的信号,完成退出处理工作之后,再让程序退出。

二、信号捕获处理和程序退出处理

2.1 信号捕获及处理

  1. 信号捕获需要用到signal()函数,调用该函数注册一个信号的处理动作。

头文件:#include <signal.h>
函数原型:void (*signal(int sig, void (*func)(int)))(int)
功能:设置某一信号的对应动作
参数:
sig   ——  所要处理的信号类型
func ——  描述了与信号关联的动作。一共有三种取值,第一种是自定义的信号处理函数;第二种是SIG_IGN,即忽略信号;第三种是SIG_DFL,即设置系统对信号的默认处理。

  1. 下面是比较常见的标准信号:
信号描述
SIGABRT由调用abort函数产生,进程非正常退出
SIGALRM用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS某种特定的硬件异常,通常由内存访问引起
SIGFPE数学相关的异常,如被0除,浮点溢出,等等
SIGINT由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGPIPE在reader中止之后写Pipe的时候发送
SIGTERM请求中止进程,kill命令缺省发送
SIGSEGV非法内存访问

2.2 程序退出处理

  程序退出处理可通过捕获退出事件,注册回调函数进行处理,使用到的是atexit()函数。

头文件:#include <stdlib.h>
函数原型:void atexit(void (*func)(void));
功能:注册终止函数(即main执行结束后调用的函数)。
注意:exit调用这些注册函数的顺序与它们 登记时候的顺序相反。同一个函数如若登记多次,则也会被调用多次。

2.3 代码示例

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

void exitHandle(void);
void sigHandle(int sig);

int main(int argc, char *argv[])
{
    //注册回调函数,程序调用 exit 或 mian函数return 或 最后一个线程正常退出时,捕获退出事件,执行退出处理
    atexit(exitHandle);
	
	//捕获异常信号,并做相应处理
    signal(SIGPIPE, SIG_IGN);	//忽略信号
    signal(SIGINT, sigHandle);  //Ctrl + C
    signal(SIGTERM, sigHandle); //kill发出的软件终止
    signal(SIGBUS, sigHandle);  //总线错误
    signal(SIGSEGV, sigHandle); //非法内存访问
    signal(SIGFPE, sigHandle);  //数学相关的异常,如被0除,浮点溢出等
    signal(SIGABRT, sigHandle); //由调用abort函数产生,进程非正常退出
	
	while(1) {
		//功能处理...
		sleep(1);
	}
	
	return 0;
}


//进程退出处理,程序调用 exit 或 main函数return 或 最后一个线程正常退出
void exitHandle(void)
{
    //handle
}

//信号处理
void sigHandle(int sig)
{
    switch (sig) {
    case SIGINT:
		printf("*** catch signal : SIGINT, value = %d\n", sig);
        break;
    case SIGTERM:
		printf("*** catch signal : SIGTERM, value = %d\n", sig);
        break;
    case SIGBUS:
		printf("*** catch signal : SIGBUS, value = %d\n", sig);
        break;
    case SIGSEGV:
		printf("*** catch signal : SIGSEGV, value = %d\n", sig);
        break;
    case SIGFPE:
		printf("*** catch signal : SIGFPE, value = %d\n", sig);
        break;
    case SIGABRT:
		printf("*** catch signal : SIGABRT, value = %d\n", sig);
        break;
    default:
		printf("*** catch unknown signal, value = %d\n", sig);
        break;
    }
    exit(0); //调用exit退出程序,会被捕获该事件,从而触发进程退出处理的回调函数
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶落花枯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值