异步处理方式之信号(二):可靠的信号与不可靠的信号
发布日期:2021-06-23 04:43:36 浏览次数:6 分类:技术文章

本文共 2539 字,大约阅读时间需要 8 分钟。

不可靠的信号

4.1 什么是不可靠的信号

​ 在早期的Unix版本中,信号是不可靠的。这里的不可靠指的是:信号可能会丢失(一个信号已经发生了,但是该进程却不知道这一点)。除此之外,进程对信号的控制能力也特别差,它只能捕捉或者忽略信号。但是有时用户希望通知内核阻塞某个信号,不要忽略该信号;而在进程准备好处理该信号时在由内核重新通知该进程。

某些书籍提到signal函数每触发一次,得重新调用signal重新注册安装信号处理函数。这已经很很久以前的了,现在是一次signal注册,之后多次使用,无需每次在信号处理函数中重新调用signal函数(Linux便是如此)

4.2 信号丢失的例子:

​ 正常情况下,信号的发生频率很低,因此信号丢失的情况比较少。但是如果信号发生的频率比较高,且信号处理函数费时的话就很容易发生信号丢失的情形。下面我们通过在信号处理函数中调用延时函数模拟实现:

/*************************************************************************             > File Name: signal_lost.c             > Author: Toney Sun             > Mail: vip_13031075266@163.com       > Created Time: 2020年04月27日 星期一 15时03分18秒 ************************************************************************/#include
#include
extern void my_msleep(int mseconds);//自己实现的睡眠函数,与库函数并无区别static void sig_handler(int signo){
static int flag=0; printf("sig_handler finish: flag=%d\n", flag); if(signo == SIGINT){
printf("Recieved SIGINT signal\n"); flag++; my_msleep(5000);//延时5秒 }else{
printf("sig_handler receieve Error signal\n"); } printf("sig_handler finish: flag=%d\n", flag);}int signal_lost_test(){
if(signal(SIGINT, sig_handler)==SIG_ERR){
printf("SIGINT handle function register error\n"); } }

执行结果如下:

toney@ubantu:/mnt/hgfs/em嵌入式学习记录/schedule调度器$ ./demo.out ^Csig_handler finish: flag=0Recieved SIGINT signal^C^C^Csig_handler finish: flag=1sig_handler finish: flag=1Recieved SIGINT signalsig_handler finish: flag=2

运行程序后我是通过连续按下四次“Ctrl+C”,产生四个SIGINT信号,但实际上只捕获了其中的两个信号,另外两个则丢失了。之所以说丢失,是因为程序只打印了两次信号处理函数中的信息,该进程也只知道发生了两次事件。出现这种情形的主要原因在于信号处理程序处理的太慢(程序中我们把她睡了会儿),而信号又发生的太频繁,CPU处理不过来导致的。

​ 此外,上述结果中还有个奇怪的现象:信号处理程序不是一次性执行完毕的(专业点称为存在竞态),而是在第一个执行过程中又去相应下一个信号处理函数,等下一个处理完毕了再回来继续处理先前未执行完毕的信号处理函数。这个现像应该在编写程序中特别注意下。

5. 可靠的信号

​ 在第4部分,我们简要的说明了下什么是不可靠的信号,这里我们再来简要的说明下什么是可靠的信号。

5.1 常见的术语

  • 递送: 当对信号采取某种动作时,我们说向进程递送了一个信号。
  • 未决的:在信号产生(generate)和信号递送之间的这段时间间隔内,称信号为未决的(pending)

5.2 可靠的信号说明

​ 进程可以选择使用“阻塞信号递送”。如果为进程产生了一个阻塞的信号,而且对信号的动作是系统默认动作或捕捉该信号(非忽略状态),则为该进程将此信号保持为未决状态,直到该进程对此信号接触阻塞状态(或者修改为忽略此信号)。

​ 内核在递送一个原来被阻塞的信号给进程时,才决定对它的处理方式(因此之前的状态称为未决的)。于是乎进程在信号递送之前是可以修改对该信号的动作。系统可以调用sigpending函数来判断哪些信号是设置为阻塞同时悬而未决的。

​ 如果进程在解除多某个信号阻塞之前,该信号已经发生了多次(就是我们4.2的例子),那么该如何处理呢?目前大多数系统仍然是只递送一次该信号,也就是说不支持信号排队

​ 每一个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞递送到该进程的信号集。对于每一种可能的信号,该屏蔽字中都有与之相对应的位。如果该位被设置,则当前进程会阻塞该信号。程序中可以使用sigprocmask(后面我会详细说明)来查询和设置当前进程的信号屏蔽字。

​ 信号编号可能会超过一个整数所包含的二进制位数(32位系统是32位),因此POSIX.1专门定义了一个新的类型sigset_t,它可以容纳一个信号集。信号屏蔽字就存放在其中一个信号集中。后面我们对这部分进行详细说明。

转载地址:https://blog.csdn.net/s2603898260/article/details/105793208 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:杭州印迹
下一篇:匆匆峨眉,灿若千阳

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年03月08日 13时55分35秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

php页面引用公共文件,WeiPHP插件模板中快速引入公共模板文件 2019-04-21
php tracy,admin.php 2019-04-21
php访问父类的所有属性,php – 在父类中使用$this仅在子类中显示父类属性 2019-04-21
oracle比较强大的函数,SQL和ORACLE函数比较 2019-04-21
oracle12c order by,oracle 数据库中order by 的一些高级用法 2019-04-21
oracle8i substr,Oracle中的INSTR,NVL和SUBSTR函数的用法详解 2019-04-21
导出oracle11g的空表,轻松解决oracle11g 空表不能 exp 导出 的问题。 2019-04-21
php把整数拆分成数组,数组拆分处理(整数时的处理),该怎么处理 2019-04-21
oracle numlist,oracle sql str2numlist numtabletype 2019-04-21
php红包平均分配,红包平均分配算法 2019-04-21
linux磁盘的命令是,linux磁盘相关的命令 2019-04-21
linux服务器 缓存,Linux服务器内存使用分析及内存缓存 2019-04-21
linux查进程内存问题,关于linux 查看服务进程内存,cpu,内存占用的一些基础命令... 2019-04-21
linux英文包安装教程视频,Linux源码包安装过程讲解 2019-04-21
linux 关闭rsync服务器,linux下配置rsync服务器和实时同步 2019-04-21
linux初始化TCP服务失败,深入Linux系统追踪TCP初始化 2019-04-21
arch Linux添加源,在Arch Linux系统中使用Archlinuxcn源(清华源)的方法 2019-04-21
私人linux远程连接,Linux远程连接 - osc_5g1gl9wp的个人空间 - OSCHINA - 中文开源技术交流社区... 2019-04-21
windows文件迁移到linux,从Windows到Linux迁移之文件服务器(Samba和AD完美结合) 2019-04-21
linux下vi编辑器的命令大全,linux下VI编辑器命令大全(超级完整版) 2019-04-21