Linux信号介绍

一、信号的基本概念

在我们日常的生活当中,会看到许多信号,比如说:过马路的时候的交通信号灯,当我们看到红灯的时候,就会停下来等待,当我们看到绿灯的时候,会选择通行。而在我们的进程执行时,比如说:用户在终端按下Ctrl-C产生2号SIGINT信号,操作系统会在当前进程的PCB中对应的信号位图中修改第二个比特位(由0写为1),后面会详细介绍到。

对于信号我们需要建立以下的认知:(用Ctrl-C为例)
1.用户按下Ctrl-C,键盘输入产生一个硬件中断。Ctrl-C产生的信号只能发给前台进程(一个命令后面加&可以放在后台运行,Shell就不会等待进程结束才能执行下一个命令)。
2.Shell可以同时运行一个前台进程和多个后台进程,而Ctrl-C产生的信号只有前台进程可以接收到。
3.信号也是一部分的执行流,一个进程内可能有多个执行流,而且信号对于进程的控制来说是异步的
4.程序中有系统调用,则进入内核态,执行后,从内核态返回到用户态之前,首先处理PCB中记录的信号。

查看系统定义的信号列表
这里写图片描述
1~31非实时信号,发送的信号可能会丢失,不支持信号排队。
34~64实时信号,支持信号排队,发送的多个实时信号都会被接收。

下面介绍几个常见的非实时信号
1.SIGHUP:当用户退出Shell时,由该Shell启发的所有进程都退回接受到这个信号,默认动作为终止进程
2.SIGINT:进程终止信号,在用户键输入INTR字符(通常是Ctrl-C发出),用于通知前台进程组终止进程。默认动作是终止进程并产生core文件。
3.SIGQUIT:当用户组合键产生该信号,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为终止进程并产生core文件。
4.SIGILL:CPU检测到某进程执行了非法指令。默认动作为终止进程并产生core文件。
6.SIGABRT:调用abort函数时产生该信号。默认动作为终止进程并产生core文件。
9.SIGKILL:无条件终止进程。本信号不能被忽略、处理和阻塞。默认动作为终止进程,他向管理员提供了一种可以杀死任何进程的方法。
13.SIGPIPE:管道破裂。通常在进程间通信产生,管道读端不读且关闭,写端一直写。
14.SIGALRM:时钟定时信号。计算的是实际的时间或时钟时间。
15.SIGTERM:程序结束信号。与SIGKILL不同的是该信号可以被阻塞和处理。通常要求程序自己正常退出,Shell命令kill缺省这个信号。如果进程终止不了,我们才尝试SIGKILL。
17.SIGCHLD:子进程结束,父进程会收到这个信号。
如果父进程没有处理该信号,也没有等待子进程,子进程会在内核进程表中占有表项,该进程就被称为僵尸进程。

二、产生信号的方式

1、通过终端按键产生信号
我们知道,SIGQUIT的默认动作是终止进程并且Core Dump。那什么是Core Dump呢?
当程序运行的过程中异常终止或崩溃,操作系统将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫做Core Dump(核心转储),我们可以认为Core Dump是“内存快照”,但实际上,除了内存信息外,还有些关键的程序运行状态也会同时dump下来,例如:寄存器信息、内存管理信息、其他处理器和操作系统状态和信息。Core Dump对于程序员来说是非常有帮助的。
这里写图片描述
系统默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,所以不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。
这里写图片描述
我们写一个死循环,在前台运行这个程序,一直是死循环,不会报错。然后输入Ctrl-\,Core Dump了。我们可看到产生一个core.2936文件,.后面的为文件号
这里写图片描述
我们开始调试程序,core-file core.2936,就可以看到我们程序出错的地方了。
这里写图片描述
2、调用系统函数向进程发信号
这里写图片描述
kill函数/raise函数
说明:kill函数可以给指定的进程发送信号,raise函数实现的是自己给自己发送信号,成功返回0,错误返回-1。
这里写图片描述
这里写图片描述
abort函数
说明:abort函数使当前进程接收信号而异常终止,给自身法6号信号SIGABRT
这里写图片描述
3、由软件条件产生信号
SIGPIPE就是由软件条件产生的信号,管道读端不读且关闭,写端一直写
SIGALRM信号
介绍这个信号前,我们先认识一个函数alarm
说明:设定一个闹钟,告诉内核在senconds秒后给当前进程发14号SIGALRM信号,该信号的默认动作是终止当前进程。
参数设为0,表示取消闹钟;
参数设为n,表示n秒后发送信号
函数返回值是0或以前设定闹钟时间还余下的秒数
这里写图片描述
我们实现一个程序,该程序的功能是2秒内不断地数数,2秒到了后就会被SIGALRM信号终止。
这里写图片描述
4、硬件产生信号
硬件异常产生信号,硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如:除0异常,CPU的运算单元会产生异常,内核可以将该异常解释为SIGFPE信号发送给进程。还有使用非法地址,内存管理单元(MMU)会产生异常,该 异常被内核解释为SIGSEGV信号发送给进程。

三、阻塞信号

我们首先来认识几个概念:
1.信号递达:实际执行信号的处理动作
2.信号未决:信号从产生到递达之间的状态
3.位图(BitMap):位图是一个数组的每一个数据的每一个二进制表示一个数据,0表示数据不存在,1表示数据存在。

还记得我们一开始介绍到的产生信号的实质就是操作系统将信号位图的对应位置的比特位由0改为1,有了这个认识,其实每个信号都有两个标志位,分别为:阻塞(block)、未决(pending),我们前边一直说的就是这个pending,还有一个函数指针表示处理动作(handler)。
这里写图片描述
注意:由于每个信号只有一个bit位的标志(0/1),同一个信号产生了多少次,阻塞了多少次怎么存储,因此我们用sigset_t来存储,表示信号集类型。
其中,阻塞信号集也被称作为信号屏蔽字。我们分清两个概念,阻塞和忽略。

阻塞:未递达
忽略:已递达,只是一种处理的动作

信号处理方式(handler)
1.忽略。
2.执行默认动作。
3.提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉一个信号。

信号集操作函数
1.sigemptyset函数:初始化set所指向的信号集,使其所有信号对于的bit清零
2.sigfillset函数:初始化set所指向的信号集,使其所有信号对于的bit置1
3.sigaddset函数:添加signum信号
4.sigdelset函数:删除signum信号
5.sigismember函数:判断signum信号是否在信号集中
这里写图片描述
说明:前四个函数均是成功返回0,出错返回-1,sigisnumber是一个布尔函数,若该信号在信号集中,返回1,不在返回0,出错返回-1。

sigprocmask函数
说明:该函数可以读取或更改进程的信号屏蔽字(block)
how参数的可选值:SIG_BLOCK(添加到当前信号屏蔽字的信号) SIG_UNBLOCK(解除当前信号屏蔽字中解除阻塞的信号) SIG_SETMASK(设置当前信号屏蔽字为set所指向的值)
set:更改进程当前信号屏蔽字
oldset:原来的信号屏蔽字
这里写图片描述
sigpending函数
说明:读取当前进程的未决信号
这里写图片描述
我们来写一个代码
这里写图片描述
实现的是信号的捕捉,我们阻塞了SIGINT信号,当键盘输如组合键Ctrl-C时,使得SIGINT信号处于未决状态,不被处理。
这里写图片描述
捕捉信号
我们前边提到的信号处理handler自定义方法就是信号的捕捉。
信号捕捉过程如下图所示:
这里写图片描述
认识几个函数:
sigaction函数
说明:读取和修改与指定信号相关联的处理动作。act和oldact指向sigaction结构体
这里写图片描述
sigaction结构体
这里写图片描述
pause函数
说明:使调用进程挂起直到有信号递达,如果信号的处理动作为忽略,则进程处于挂起状态;如果处理动作为终止进程,则进程终止;如果处理动作为捕捉,则调用了信号处理函数后返回-1。
这里写图片描述
大家一定都使用过sleep函数,休眠seconds秒,在Windows下单位是毫秒,相同作用的函数有usleep函数,单位为微秒。
这里写图片描述
我们来alarm和pause实现sleep函数
这里写图片描述
说明:mysleep函数中调用sigaction函数注册了SIGALRM信号的用户自定义的处理函数sig_alarm。
1.我们调用alarm函数设定闹钟,告诉内核senconds秒后给当前进程发送SIGALRM信号。
2.调用pause函数等待,内核切换到其他进程运行。返回到用户态处理未决信号,处理方法为sig_alarm,这里函数内部什么都没做,但必须有,因为不注册的话pause不会返回。
3.进入sig_alarm函数时,SIGALRM信号被自动屏蔽(block由0改为1),从该函数返回时该信号自动解除屏蔽。然后自动执行系统调用sigreturn再次进入内核,再返回用户态继续执行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值