linux系统下进程的信号(signal)处理流程是怎么样的?

作者:peilin song
链接:https://www.zhihu.com/question/24913599/answer/115102869
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最近在正好用到这部分内容,刚刚研究过,不算深入,简单说说我的认识吧。

我想先从一些机制和原理开始说,会比较清楚。

信号是一种软件层面上对中断的模拟,而这种软件模拟的信号或者说中断的产生,有三大类:

1. 硬件异常产生的错误。比如非法访问内存,除数为0...
2. 外部信号。键盘上的Ctrl-C产生SGINT信号,定时器到期产生SIGALRM…
3. 显示的请求。 主要是通过Kill函数发送信号给指定进程。

在Linux里面每个进程都是按照进程描述符 task_struct 结构创建的,还有一个叫task vector的东西从名字上就能看出来这是一个数组,这里面保存的是指向每一个进程的指针,即指向每一个task_struct的指针,因此一个Linux系统最大的进程数,取决于task vector这个数组的大小,一般默认是512个。

在进程描述符task_struct里面,其中一项是Signal_Strct,在Signal_Strct这里面有一项list_head的描述符,在这里面有一个sigset_t表,定义了64种信号的所代表的含义。

铺垫了很多,其实主要是为了铺垫64种信号存放的位置。也就是说在每个进程之中,都有存着一个表,里面存着每种信号所代表的含义,而这也是信号机制的根本。

由于信号的触发和发送是随机的,也就是异步的。接收进程是无法预知什么时间,会收到哪个信号的。下面就开始讲下信号的详细发送机制,举例说明,如果有A,B两个进程,A进程接收到出发条件,开始发送信号给B进程,信号并不是直接从进程A发送给进程B,而是要通过内核来进行转发。之所以要通过内核来转发,这样做的目的应该也是为了对进程的管理和安全因素考虑。因为在这些信号当中,SIGSTOP和SIGKILL这两个信号是可以将接收此信号的进程停掉的,而这类信号,肯定是需要有权限才可以发出的,不能够随便哪个程序都可以随便停掉别的进程。

A进程发送的信号消息,其实就是根据上面的那个信号表,根据需要对相应的表项进行设置。内核接受到这个信号消息后,会先检查A进程是否有权限对B进程的信号表对应的项进行设置,如果可以,就会对B进程的信号表进行设置,这里面信号处理有个特点,就是没有排队的机制,也就是说某个信号被设置之后,如果B进程还没有来及进行响应,那么如果后续第二个同样的信号消息过来,就会被阻塞掉,也就是丢弃。

内核对B进程信号设置完成后,就会发送中断请求给B进程,这样B进程就进入到内核态,这个时候进程B根据那个信号表,查找对应的此信号的处理函数,然后设置frame,设置好之后,跳回到用户态执行信号处理函数,处理完成后,再次返回到内核态,再次设置frame,然后再次返回用户态,从中断位置开始继续执行。

这个frame其实就是在用户态和内核态之间跳转的时候,对堆栈现场的压栈保存。

大致的原理就是这么一个过程,在真正使用的时候,就比较简单了,用kill函数发送信号,在接收进程里,通过signal或者signalaction函数调用sighandler,来启动对应的函数处理信号消息。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值