狂自私

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

使用sigaction函数

sigaction函数

修改信号处理动作(通常在Linux用其来注册一个信号的捕捉函数)

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);  成功:0;失败:-1,设置errno

参数:

act:传入参数,新的处理方式。oldact:传出参数,旧的处理方式。

struct sigaction结构体

    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_restorer:该元素是过时的,不应该使用,POSIX.1标准将不指定该元素。(弃用)

sa_sigaction:当sa_flags被指定为SA_SIGINFO标志时,使用该信号处理程序。(很少使用)

重点掌握:

sa_handler:指定信号捕捉后的处理函数名(即注册函数)。也可赋值为SIG_IGN表忽略 SIG_DFL表执行默认动作

sa_mask: 调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。注意:仅在处理函数被调用期间屏蔽生效,是临时性设置。用sigaddset函数添加需要被捕捉的信号。

sa_flags:通常设置为0,表使用默认属性:为0的时候,可以屏蔽正在处理的信号(若在处理2号信号时又有2号信号,则此时传来的2号信号会被屏蔽)。

不多说了,上代码:

#include <stdlib.h>

#include <stdio.h>

#include <signal.h>

void func(int signal)

{

    printf("%d号信号被捕捉。\n", signal);

}

int main(void)

{

    struct sigaction act, oldact;

    act.sa_handler = func;

    act.sa_flags = 0;//为0的时候,可以屏蔽正在处理的信号(若在处理2号信号时又有2号信号,则>会被屏蔽)

    sigemptyset(&act.sa_mask);//sa_mask是一个临时信号集,将其清零(初始化I)

    sigaddset(&act.sa_mask, SIGQUIT);//将3号信号添加到信号集,即:3号信号就是我们在处理2号信号的时候需要屏蔽的那个信号,也许可以添加其他信号,比如20号信号

    sigaddset(&act.sa_mask, SIGTSTP);

    int s_ret = sigaction(SIGINT, &act, &oldact);

    if (0>s_ret)

    {

        perror("sigaction error");

        exit(1);

    }

    while (1);

    return 0;

}

结果:我的环境是win10子系统,经过我的测试,ctrl+\这个组合键不被支持,不能发送3号信号。所以在我按下ctrl+\之后并没有反应,程序依旧执行,但是在真正的Linux独立系统中,按下之后该程序会被杀掉的,就如同我按下ctrl+z之后,程序挂起:接下来kill掉就是了。

   

———————————————隔了不到十分钟又来更新的分割线——————————————-

我们来看看信号捕捉特性

进程正常运行时,默认PCB中有一个信号屏蔽字,假定为,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为

XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。

阻塞的常规信号不支持排队,产生多次只记录一次。(后32个实时信号支持排队)

为了模拟这个3所说的内容,我们这样改代码:

void func(int signal)

{

    printf("%d号信号被捕捉。\n", signal);

    sleep(5);//睡眠十秒,模拟处理信号的函数处理时间很长的那种情况

    puts("———————————— - fiish———————");

}

我的测试结果:

第一次只按一次ctrl+c,显示被捕捉之后疯狂的按ctrl+cfinish之后显示信号再次被捕捉,然后疯狂按ctrl+cctrl+z。结果是:那么多次的ctrl+c只执行了三次,多次的ctrl+z也只是被执行了一次。其实原理很好理解的,我们知道,当信号被阻塞时,未决信号集中的相应编号的位置会有0翻转为1,信号集是什么?是位图。他不能为多次的相同的信号计数。所以,再多的相同信号在系统看来也只是一个罢了。

————————————–再更新一次————————————-

signal()sigaction()函数是捕捉信号的函数么?是么?是么?是么?

不是,他俩只是注册信号捕捉函数的函数,真正动手捉信号的是内核。记得啊。本质区别的。

posted on   狂自私  阅读(2343)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示