Linux多进程18-sigaction 信号捕捉函数

#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

内核实现信号捕捉的过程

  1. 在内核中有阻塞信号集, 在我们信号捕捉处理当中, 会使用临时的阻塞信号集,当信号处理完毕会恢复到内核的阻塞信号集
  2. 在执行回调之前, 信号会默认被屏蔽掉, 等待前一个回调执行完毕
  3. 阻塞的常规信号是不支持排队的, 标志位同时只能记录一个

image

posted @ 2023-05-17 18:42  言叶以上  阅读(26)  评论(0编辑  收藏  举报