signal信号函数的使用

239 篇文章 10 订阅
141 篇文章 6 订阅

1、前言

信号有三种处理方式
1)执行默认动作;

2)忽略;//什么都不做,忽略默认动作

3)捕捉;//捕捉到信号后,不执行默认动作,而让其执行捕捉函数中内容

产生信号的五种形式:

1)按键产生,如 ctrl +c、ctrl+z,ctrl+\

2)系统调用产生,如kill函数,raise函数,abort函数

3)软件条件产生,如定时器alarm,调用函数,开始计时,时间到,发送信号

4)硬件异常产生,如:非法访问内存(段错误)、除0(浮点数例外)、内存对齐出错(总线错误)

5)命令产生,如kill命令
————————————————

#define SIG_ERR             ((void(*)(_SIG_ARGS)) -1)
#define SIG_DFL             ((void(*)(_SIG_ARGS))  0)
#define SIG_IGN             ((void(*)(_SIG_ARGS))  1)
#define SIG_HOLD            ((void(*)(_SIG_ARGS))  2)

以上宏定义是将-1、0、1、2强制类型转换成了指针,即以-1、0、1、2为地址的空间。

2、我们在捕捉函数中,会将一个标志位置1,

该标志位==1时,会完成清理线程资源,终止死循环等工作。

编程中经常会用到终止进程,比如,终端中输入kill -15 进程号     命令来终止进程,终止前我们需要先做以下工作:

        1)清理进程用到的系统资源,比如关闭数据库,关闭socket,free/delete 内存资源;

       2) 终止死循环,通过iExitFlag = 1;的方式退出循环。

以上工作我们会在死循环中判断标志位:

void* thread_func(void *arg)
{
    if(iExitFlag == 1)
    {
        free(pt);
        close();
        ......
        exit(0);
    }
    //do sth.
}

3、示例

示例1:

//我们只用kill -15 进程号  命令来发出命令终止进程,信号捕捉后,进行终止线程,终止死循环操作。

void signal_func(int flag)
{
    if(flag == SIGTERM)
    {
        iExitFlag = 1;     //终止线程标志位
        cout<<"process exit"<<endl;
        sleep(1);//等待线程结束
        exit(0);
    }
}

int  main()
{

    //屏蔽前31个信号,但其实信号9是无法忽略的。
    for(int sign = 1; sign <=31; sign ++)
            signal(sign, SIG_IGN);
    if(signal(SIGTERM, signal_func) == SIG_ERR)
    {
            printf("SIGTERM(signal_func) is fail!");
            exit(0);
    }
    return 0;
}

示例2:

SIGTERM  ---->kill -15

SIGQUIT-------> ctrl +/

SIGABR------->abort()函数产生

   

void signal_func(int flag)
{
    if(flag == SIGTERM || flag == SIGQUIT || flag == SIGABRT)
    {
        cout << "signal sucess" << flag;
        iExitFlag = 1;
        cout << "Exit!";
        sleep(3); // 等待线程结束
        exit(EXIT_SUCCESS);
    }
}

int main()
{
    if(signal(SIGABRT, signal_func) < 0 ||signal(SIGTERM, signal_func) < 0 ||

            signal(SIGQUIT, signal_func) < 0 )
    {
        cout << "signal failed";
        exit(EXIT_FAILURE);
    }
    return 0;
}

4总结:

由于sighandler函数(信号捕捉函数)和main函数使用不同的堆栈空间,两者之间不存在调用和被调用的关系,属于两个独立的控制流程。

所以,调用sighandler的时候,并不会影响原程序的执行。

只是将原程序中的标志位置1了,然后sleep(1);等待原程序中资源释放,线程退出,执行exit(0);命令。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值