进程信号

进程信号

1.作用:
1.信号量和信号是两个截然不同的东西。
2.信号的作用:通知别人,发生了某件事情,尽快的去处理这件事情(操作系统通知进程发生了某个事件,打断进程当前操作,去处理这个事)。所以我们可以把信号看成是软件中断

2.如何处理一个信号:

  • 信号想要成为一个中断,首先我们必须认识这个信号,并且知道如何去处理它?

我们都知道:事件多种多样,因此信号也是多种多样。

1、查看操作系统中定义好的信号:使用kill -l命令可以查看信号种类;
用户所能看到并使用的信号共有62种,两大分类:

  • 1~31号信号:每个信号都有具体对应的事件------非可靠信号;

  • 34~ 64号信号:在操作系统中当前就没有具体对应的事件了,因此命名也稍微草率一点---- (可靠信号)。

2、信号的生命周期:
信号的产生 —> 信号在进程中注册 —> 信号在进程中注销---->处理信号 (信号的阻塞)

3、信号的产生
硬件::ctrl+c / ctrl+z (电脑中有很多快捷键)。

软件:
命令: kill -signum pid
kill命令能够杀死一个进程, 主要是因为kill命令功能是向进程发送一个信号 ,默认发送的15号终止信号。

int kill(pid_ t pid, int sig); 向指定的进程发送指定的信号

int raise(int sig);:向调用进程自身发送指定的信号

void abort(void); 向调用进程自身发送SIGABRT信号,使一个异常的进程退出

unsigned int alarm(unsigned int seconds); 

seconed秒之后给调用进程发送一个SIGALRM信号, 告诉进程时间到了。

core dump:程序异常退出时,操作系统会保存这个进程的运行信息,便于这个进程的事后调试(默认是关闭的)。

操作步骤:

ulimit -C 1024 开启core dump, 并将core文件最大大小设置为1024kb
gdb ./(loop_ test)   ->   core-file core.pid(产生的core文件) 
-> 常规的gdb调试步骤
最后注意,如果不用了,就关闭core dump。

4.信号在进程中的注册:
让进程知道自己收到了这么一个信号,进程就是一个pcb, Linux下是一个task _struct结构体;在pcb结构体中定义了一个信号的集合(位图) ;
若给进程发送一个信号,则将这个信号对应位置的二进制位置1,进程通过查看位图判断是否有信号到来,进而去处理。
在这里插入图片描述
pending信号集合:未决信号集合:
未决是一个状态,指的是信号产生了,但是还没有被处理的一个区间状态,
这个位图实际上是一个结构体;这个数组被用于实现位图,位图这个信号集合,只能用于标记进程是否收到了这个信号,无法确定这个信号收到了多少次。
因此在内核中其实还有一个链表sigqueue{… .siginfo. t…};
在这里插入图片描述

信号的注册,就是组织一个信号的信息,添加到信号链表中,并且将信号pending位图进行置位。

非可靠信号的注册:在注册信号时,判断当前信号是否已经注册过(位图是否已经为1) ;若没有注册,则添加节点,修改位图;反之,若已经注册过了,则什么也不干(这种信号在链表中就永远顶多只有一个节点,后来到达的信号就会被丢弃【事件丢失】)。

可靠信号的注册:在注册信号时,每次针对新到来的信号都会创建一个节点添加到链表中,并且位图置1;(链表中有可能有多个相同节点)。

5、信号在进程中的注销:抹除信号存在痕迹

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

6、信号的阻塞:信号的递达
进程处理一个事件,事件可以理解为就是一个功能, 在程序中,一个功能的实现单位就是一个函数进程在收到信号之后,针对这个信号的事件找到它对应的处理函数,调用函数。
在进程中标记,哪些信号注册之后,暂时不去处理,直到信号解除阻塞(阻塞一个信号被递达)。
进程pcb中有一个信号block集合—用户可以在这个集合中标记哪些信号将被阻塞。
在这里插入图片描述
每一行是一一对应的,假设这个2号信号,block集合为1,则表示这个2号信号被阻塞,暂时不能被处理。

  • 如何阻塞一个信号: 将信号添加到pcb的block集合中,则表示这个信号将会被阻塞:到来时则暂时不被处理。

== 代码中如何阻塞一个信号 ?==

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

how:即将要对pcb中block集合所作的操作;
SIG_ BLOCK(将第二个参数set集合中信号添加到block集合中;)
SIG_ UNBLOCK(将第二个参数set集合中信号从block集合中移除;)
set:信号集合(位图);
oldset:每当block集合要发生改变的时候,都会将原block集合中的数据拷贝到oldset中返回给用户,便于后期还原。

  • 定义几种信号的处理方式
signal(SIGINT, sigcb); 
signal(SIGQUIT, sigcb);
  • 阻塞上边定义的信号集合中的信号
sigprocmask(SIG_ BLOCK, &set, NULL);
  • 解除阻塞,然后观察解除阻塞后信号会不会被处理
sigprocmask(SIG_ UNBLOCK, &set, NULL);

**3.**如何处理一个信号

  • 默认处理----系统中已经定义好的默认函数。
  • 忽略处理—处理的动作就是什么都不做(依然能够信号注册,只是处理动作中什么也不做而已)。
  • 自定义处理—用户自己定义信号回调函数,然后使用这个函数的地址替换原有信号动作数组中的函数地址,也就是说,替换了信号处理动作中的回调函数。

信号处理方式的修改;

sighandler_t signal(int signum, sighandler_t handler); 
修改一个信号的处理动作中的回调函数
signum:信号值
handler:函数指针
sighandler_t--函数指针类型typedef void (*sighandler_t) (int signo)
SIG_IGN---信号进行忽略处理
SIG_DFL---信号的默认处理
signo:当信号到来时,操作系统向回调函数中传入的信号值
告诉用户本次调用这个函数,是哪个信号触发的。

处理一个信号时间:当前进程从内核态切换到用户态时进行处理。
程序从用户切换到内核有哪几种情况:

  • 中端
  • 异常
  • 系统调用接口
    自定义处理方式的捕捉流程:
    在这里插入图片描述
    注:==在所有信号中有两个信号不可被阻塞,不可被忽略,不可被自定义修改— 9-SIGKILL 19- SIGSTOP
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值