Linux信号捕捉之sigaction

进程可以通过三种方式来响应和处理一个信号:

​(1)忽略信号:即对信号不做任何处理,但是两个信号不能忽略:SIGKILL以及SIGSTOP.

(2)捕捉信号:当信号发生时,执行用户定义的信号处理函数。

(3)执行默认操作: Linux对每种信号都规定了默认操作,man 7 signal查看。

Term Default action is to terminate the process.

Ign Default action is to ignore the signal.

Core Default action is to terminate the process and dump core (see core(5)).

Stop Default action is to stop the process.

Cont Default action is to continue the process if it is currently stopped.


sigaction函数捕捉信号

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

struct sigaction 
{
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
};
/*
sa_handler : 早期的捕捉函数
sa_sigaction : 新添加的捕捉函数,可以传参, 和sa_handler互斥,两者通过sa_flags选择采用哪种捕捉函数
sa_mask : 在执行捕捉函数时,设置阻塞其它信号,sa_mask | 进程阻塞信号集,退出捕捉函数后,还原回原有的
阻塞信号集
sa_flags : SA_SIGINFO 或者0用来指定调用sa_handler还是sa_sigaction,SA_SIGINFO时为调用sa_sigaction,
           SA_RESTART 让被打断的系统调用重新开始
sa_restorer : 保留,已过时
*/
  • sigaction例子

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig_handle(int sig)
{
    puts("recv SIGINT");
    sleep(5);
    puts("end");
}

int main(int argc, char** argv)
{
    struct sigaction act;
    act.sa_handler = sig_handle;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, SIGQUIT); //当进入信号处理函数的时候,屏蔽掉SIGQUIT的递达

    sigaction(SIGINT, &act, NULL);
    while(1)
        sleep(1);
    return 0;
}

read函数的EINTR错误

    信号能中断一些系统调用,返回-1并且设置errno为EINTR,例如read write sleep等,如果想要恢复这些函数继续运行可以加上 SA_RESTART标志。

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
void sig_handle(int sig)
{
    printf("SIGINT\n");
}

int main(int argc, char** argv)
{
    char buf[10];
    struct sigaction act;
    act.sa_handler = sig_handle;
    act.sa_flags = 0;
    //act.sa_flags = SA_RESTART;  //先试一试sa_flags为0时,然后再试一试SA_RESTART的情况
    sigemptyset(&act.sa_mask);

    sigaction(SIGINT, &act, NULL);

    puts("read stdio:");
    int ret = read(STDIN_FILENO,  buf, 9);
    if(ret == -1)
    {
        if(errno == EINTR)
            perror("read:");
    }
    else
    {
        buf[ret] = '\0';
        printf("read %d : %s", ret,  buf);
    }
    return 0;
}

​ 以上的运行结果的是,act.sa_flags = 0时一旦发送了一个信号,read将被打断,返回-1,并且设置errno为EINTR。如果想打断后继续运行read,可以设置一下act.sa_flags = SA_RESTART。或者也可以使用signal函数来处理信号,signal相当于默认设置了SA_RESTART标志。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值