进程信号

1.进程信号

1.1 信号的作用
通知别人,发生了某件事情,尽快去处理这件事情(操作系统通知进程发生了某个事件,打断进程当前操作,去处理这个事件)
1.2 信号种类
查看操作系统中定义好的信号:是有kill-l可以查看信号种类
用户所能看到的信号共有62种,两大分类:
1-31号信号:每个信号都有具体对应的事件----非可靠信号
34-64号信号:在操作系统中当前就没有具体的对应实践,因此命名比较草率—可靠信号
1.3 生命周期
信号的生命周期:信号的产生–>信号在进程中注册—>信号在进程中注销—>处理信号

2.信号的产生

2.1 硬件:键盘上输入的信息 ctrl+c
2.2 软件:命令:kill -signum pid(信号值)向指定的信号发送命令
kill命令能够杀死·一个进程,主要是因为kill命令功能是向进程发送一个信号,默认发送的15号终止信号
2.3 信号产生函数:

int kill(pid_t pid,int sig);//向指定的进程发送指定的信号
int raise(int sig);//向调用进程自身发送指定的信号
void  abort(void);//向调用进程自身发送SIGABRT信号,使一个异常进程退出
unsigned int alarm(unsigned int seconds);//second秒之后给调用进程发送一个SIGALRM信号,告诉进程时间到了

core dump:程序异常退出时,操作系统会保存这个进程的运行信息,便于这个进程的事后调试(默认是关闭的)
ulimit-c 1024开启core dump,并将core文件最大大小设置为1024kb
gdb./loop_test ->core-file core.pid(产生的core文件)->常规的gdb调式步骤

3.信号在进程中注册

信号在进程中的注册:让进程知道自己收到了一个信号,进程就是一个pcb。linux下是一个task_struct结构体,在pcb结构体重定义一个信号的集合(位图),若给进程发送一个信号,则将这个信号对应位置的二进制位置为1,进程通过查看位图判断是否又信号的到来,进而去处理信号。这个位图实际上是一个sigset{unsigned long int_val[_SIGSET_NMORDS]}结构体,这个数组用于实现位图,但是位图这个信号集合只能用于标记进程是否收到了这个信号,无法确定这个信号收到了多少次,因此在内核中还有一个链表记录信号次数。
信号注册:就是组织一个信号的信息,添加到信号链表中并将信号pending(pending信号集合也叫未决信号集合:未决是一种状态,指的是信号产生了,但是还没有被处理的一个区间状态)位图进行置位。
非可靠信号的注册:在注册信号时,判断当前信号是否已经注册过(即位图是否为1),若没有注册,则添加节点修改位图;反之,若已经注册过,则什么也不干(这种信号在链表中永远顶多只能有一个节点,后来到达的信号就会被丢弃)。
可靠信号的注册:在注册信号时,针对新到来的信号都会创建一个节点添加到链表中并将位图置为1(链表中有可能会有多个相同的节点)。

4.信号在进程中的注销(抹除信号存在痕迹)

非可靠信号:删除节点,位图置0(因为非可靠节点只会注册一次,顶多只有一个节点)。
可靠节点:删除节点,判断是否还有相同节点,若没有则位图置0,表示没有这个信号,反之则位图依然为1,表示还有信号待处理。

5.信号的处理

5.1 信号的处理:信号的递达
进程处理一件事情,事情可以理解为就是一个功能,在程序中一个功能的实现单位就是一个函数,即进程在收到信号之后,针对这个信号的事件找到它对应的处理函数,调用函数。
5.2 信号的处理方式
(1)默认处理方式:在操作系统中,每个信号都有其已经定义好的默认处理方式,系统中已经定义好的默认处理动作。
(2)忽略处理:处理的动作就是什么都不做(依然能够信号注册,只是处理动作中什么也不做)。
(3)自定义处理:用户自己定义信号回调函数,然后适应这个函数的地址替换原有信号动作数组中的函数地址。
5.3 信号处理方式的修改
函数:sighandler_t signal(int sinnum,sighandler_t handler)
功能:修改一个信号的处理动作中的回调函数
参数:signum:信号值
handler:函数指针
sighandler_t----函数指针类型 typedef void(*sighandler_t)(int signo)
SIG_IGN—信号进行忽略处理 SIG_DFL----信号的默认处理
signo:当信号到来时,操作系统向回调函数中传入的信号值—告诉用户本次调用这个函数,是哪一个信号触发的
5.4 自定义处理方式的信号捕捉流程
信号处理:是当前进程运行从内核态切换用户态之前进行处理
程序从用户态切换到内核态:中断,异常,系统调用接口
自定义处理方式的信号捕捉流程:
1.程序运行在用户态主控流程,在中断、异常、系统调用的情况下,进程切换到内核态运行
2.完成内核功能之后,在即将返回用户态之前调用do_signal接口去处理信号
3.其中默认处理/忽略处理方式都是在内核中完成的,但是自定义接口是用户自己定义的函数运行的用户态
4.因此进从内核态切换到用户态运行的是信号自定义回调函数,去处理信号事件
5.在信号处理函数运行完毕后,调用sigreturn返回内核态
6.当没有信号待处理,则调用sys_sigreturn返回用户态主控流程从之前运行的地方开始继续运行

6.信号的阻塞

6.1 信号的阻塞:在进程中标记,阻塞一个信号被递达,那些信号注册之后,暂时不去处理,直到信号解除阻塞。
6.2 如何阻塞:进程pcb有一个信号block集合—用户可以在这个集合中标记那些信号将被阻塞。
阻塞一个信号:将信号添加到pcb的block集合中,则表示这个信号将会被阻塞,到来时则暂时不被处理。
在代码中如何阻塞一个信号:
函数:int sigprocmask(int how, const sigset_r *set, sigset_t *oldset);
参数:
how:即将要对pcb中block集合所进行的操作
SIG_BLOCK:将第二个参数set集合中信号添加到block集合中/将set集合加入阻塞
SIG_UNBLOCK:将第二个参数set集合中信号从block集合中移除/将set集合解除阻塞
SIG_SETMASK:使用第二参数set集合中信号替换block集合中的数据
set:信号集合(位图)
oldset:每当block集合要发生改变的时候,都会将原block集合中的数据拷贝到oldset中返回给用户,便于后期还原。
6.3 注意
在所有信号中,有两个信号无法被阻塞,无法被自定义,无法被忽略:9,SIGKILL/19,SIGSTOP。
什么情况下一个进程无法被杀死:僵尸进程,处于停止状态的进程(只能被9号杀死)、信号被阻塞/忽略处理的进程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值