千家信息网

Linux如何实现信号捕捉

发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,这篇文章主要介绍了Linux如何实现信号捕捉,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。##signal函数函数原型:sighand
千家信息网最后更新 2025年02月05日Linux如何实现信号捕捉

这篇文章主要介绍了Linux如何实现信号捕捉,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

##signal函数

函数原型:

sighandler_t signal(int signum, sighandler_t handler);

其中,sighandler定义是这样的:typedef void (*sighandler_t)(int);

函数作用:注册一个信号捕捉函数,也就是说,收到了某个信号,就执行它所注册的回调函数。

函数参数:

  • signum:信号编号,尽量用宏来写,而别用数字,这样更适合跨平台;

  • handler:注册的回调函数;

函数缺陷:

由于历史原因,该函数在不同版本的Unix和Linux系统中可能起到的效果不一样,所以跨平台性不佳,尽量避免使用它,取而代之使用通用性更好的sigaction函数。

 #include   #include    void func()  {      printf("SIGQUIT catched!\n");  }   int main() {     signal(SIGQUIT, func);     while(1); }

##sigaction函数

函数原型:

int sigaction(int signum, const struct sigaction act, struct sigaction oldact);

函数作用:与signal函数类似,用来注册一个信号捕捉函数;

返回值:

成功:0;失败:-1,并设置errno;

参数:

  • signum:信号编号,尽量用宏来写,而别用数字,这样更适合跨平台;

  • act:传入参数,新的信号捕捉方式;

  • oldact:传出参数,旧的信号捕捉方式

这里特别要注意参数中struct sigaction结构体,这也是这个函数的难点所在,下面详细说明:

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和sa_sigaction这两个成员一个已经被弃用了,另一个很少使用,所以我们暂且不管它们,重点掌握剩下的三个。

(1) sa_handler:指定信号捕捉后的处理函数,即注册回调函数。该成员也可以赋值为SIG_IGN,表示忽略该信号,也可注册为SIG_DFL,表示执行信号的默认动作。

(2) sa_mask:临时阻塞信号集(或信号屏蔽字)先来看这样一个情景:

某个信号已经注册了回调函数,当内核传递这个信号过来时,会先经过一个阻塞信号集,先阻塞掉部分信号。再去执行对应的回调函数。如下图示:

假如说,这个回调函数回调执行的时间比较长,比如2秒,在这2秒里,又有其它的信号过来,那进程是暂停当前回调函数,去响应新的信号,还是不管新来的信号,先把当前回调函数处理完再说?

正确的做法是,在执行回调函数期间,使用sa_mask临时的去替代进程的阻塞信号集,保证回调函数安心的执行完毕,再解除替代。注意:这个过程仅仅发生在回调函数执行期间,是临时性的设置。

(3) sa_flags:通常设置为0,表示使用默认属性。

再来看另外一个场景:

比如进程对SIGQUIT注册了回调函数,当回调函数在执行期间,又来了SIGQUIT函数,这时,进程是响应还是不响应该信号?这就是sa_flags的一个作用,当其设置为0时,表示使用默认属性,也就是先不响应该信号,而是执行完回调函数再处理此信号。

另外,阻塞的常规信号不支持排队,也就是说,执行回调函数期间,再来千百个同个信号时,系统只记录一次。而后面的32个实时信号则支持排队。

 #include   #include   #include    void func(int signal)  {      printf("SIGQUIT catched!\n");      sleep(2);   //用来模拟回调函数执行很长时间      printf("func finished!\n"); }  int main() {     struct sigaction act;     act.sa_handler = func;     sigemptyset(&act.sa_mask);  //先清空临时阻塞信号集     sigaddset(&act.sa_mask, SIGINT);    // 执行回调函数期间,屏蔽SIGINT     act.sa_flags = 0;      sigaction(SIGQUIT, &act, NULL); //注册回调函数      while(1);      return 0; }

感谢你能够认真阅读完这篇文章,希望小编分享的"Linux如何实现信号捕捉"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

函数 信号 阻塞 参数 篇文章 进程 也就是 作用 原型 成员 结构 处理 支持 三个 也就是说 属性 执行期 数字 方式 系统 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 松江区智能软件开发售后服务 专升本数据库原理及应用难吗 米多科技与武汉互联网 工地安全风险数据库 关于学校学生网络安全 宁波微猎网络技术有限公司 华为全球网络安全和隐私官 河北同步网络时钟服务器虚拟主机 杭州软件开发师工资 超凡先锋为啥没有服务器 网络安全中扫描分为哪两类 myd数据库数据如何打开 怎么进国企软件开发 河南璨宇网络技术服务有限公司 达梦数据库默认uuid 网络安全技术培训方案 球球大作战中心服务器怎么安装 微信小程序用不用连接数据库 网络安全属于哪一类专业 百里网络技术有限公司 无感洗车软件开发 小学网络安全教育方案 医院网络安全简报 成华区宣传部关于招聘网络技术 绝地求生服务器开机时间 宁波微猎网络技术有限公司 软件开发应用实习周记报告 闵行区一站式软件开发问答知识 bert神经网络技术是什么 关于网络安全的前言
0