#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
- 功能: 检查或者改变信号的处理, 信号捕捉
- 参数:
- signum: 需要捕捉的信号的编号或者宏值(信号的名称)
- act: 捕捉到信号之后的处理动作
- oldact: 上一次对信号捕捉相关的设置, 一般不使用, 传递NULL
- 返回值:
成功0, 失败-1
struct sigaction {
void (*sa_handler)(int); //函数指针, 指向的函数就是信号捕捉到之后的处理函数
void (*sa_sigaction)(int, siginfo_t *, void *); //不常用
sigset_t sa_mask; //临时阻塞信号集, 在信号捕捉函数执行过程中, 临时阻塞某些信号
int sa_flags; //使用哪一个信号对捕捉到的信号进行处理
这个值可以是0, 表示使用sa_handler, 也可以是SA_SIGINFO表示使用sa_sigaction
void (*sa_restorer)(void); //已废弃, NULL
};
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <sys/signal.h>
//过3S后, 每隔2S定时一次
void myalarm(int num)
{
printf("捕捉到了信号的编号是: %d\n", num);
printf("xxxxxxx\n");
}
int main(int argc, char const *argv[])
{
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = myalarm;
sigemptyset(&act.sa_mask); //清空临时阻塞信号集
//注册信号捕捉
sigaction(SIGALRM, &act, NULL);
struct itimerval new_value;
//设置间隔时间
new_value.it_interval.tv_sec = 2;
new_value.it_interval.tv_usec = 0;
//设置延迟时间, 3S后开始第一次定时
new_value.it_value.tv_sec = 3;
new_value.it_value.tv_usec = 0;
int ret = setitimer(ITIMER_REAL, &new_value, NULL);
if (ret == -1)
{
perror("setitimer err");
exit(0);
}
printf("定时器开始了...\n");
// getchar();
while (1)
;
return 0;
}
运行
$./sigaction
定时器开始了...
捕捉到了信号的编号是: 14
xxxxxxx
捕捉到了信号的编号是: 14
xxxxxxx
...
...
^C
内核实现信号捕捉的过程
- 在内核中有阻塞信号集, 在我们信号捕捉处理当中, 会使用临时的阻塞信号集,当信号处理完毕会恢复到内核的阻塞信号集
- 在执行回调之前, 信号会默认被屏蔽掉, 等待前一个回调执行完毕
- 阻塞的常规信号是不支持排队的, 标志位同时只能记录一个