Linux信号机制

Linux信号机制是进程间消息传递的一种方法,是在软件层次对中断机制的一种模拟,即软中断。

1. 信号分类

信号可以分为可靠信号和不可靠信号,或者实时信号和非实时信号。从UNIX系统继承过来的信号都是不可靠信号,信号值为[1,SIGRTMIN],表现在信号不支持排队,如果同一个信号已经有挂起的,新触发的信号就会被丢弃。后来Linux改进了信号机制,增加了32种信号[SIGRTMIN,SIGRTMAX],这些信号都是可靠的信号,表现在信号支持排队,不会丢失。信号的性质和调用的信号安装、发送接口无关。

2. 信号响应时机

Signal的响应时间点是进程从内核态返回用户态时(系统调用、中断),运行在进程上下文(用户态)。

  1. 用户线程运行在用户态。立刻打断当前线程的运行,执行用户自定义的信号处理函数。

2. 用户线程运行在内核态。不会打断当前的执行流程,等到从内核态返回用户态的时候,先处理超时信号,在当前线程上下文运行用户注册的信号处理函数,然后再返回用户态执行之前的流程。

       3. 组塞在系统调用。

       1)可被中断的系统调用。打断当前的阻塞状态返回用户态,在返回用户态时先处理超时信号,在当前线程上下文运行用户注册的信号处理函数,然后再返回用户态,系统调用接口返回-1,并将错误码errno设置为EINTR。

      2)不可被中断的系统调用。不打断当前的系统调用,等待系统调用自己返回,等到从内核态返回用户态的时候,先处理超时信号,在当前线程上下文运行用户注册的信号处理函数,然后再返回用户态执行之前的流程。如下图所示(图片源自网络)。

                          

 

备注:什么是可被中断的系统调用和不可被中断的系统调用?内核是通过wait queue来实现系统调用的阻塞等待,如果调用的wait_event_interruptible系列函数,就是可被中断的系统调用;如果调用的是wait_event系列函数就是不可被中断的系统调用。

4. 信号的处理方式

忽略信号。大部分信号都可以被忽略,除了SIGSTOP和SIGKILL,这是系统或者Root用户杀掉进程的手段。

捕获信号自定义处理函数。注册自定义的信号处理函数,除了SIGSTOP和SIGKILL。

系统默认处理。内核定义的默认动作,有5种情况:

a) 流产abort:终止进程并产生core文件。

b) 终止stop:终止进程但不生成core文件。

c) 忽略:忽略信号。

d) 挂起suspend:挂起进程。

e) 继续continue:若进程是挂起的,则resume进程,否则忽略此信号。

 5. 内核对信号的管理机制

        内核在每个进程的控制块中设计了一个Signal的位图信息,其中的每位与具体的Signal相对应,与中断机制是一致的。当系统中一个进程A通过系统调用向进程B发送Signal时,设置进程B的对应Signal位图,类似于触发了Signal对应中断,当进程B从内核态返回用户态时检查signal位图信息表是否有待处理的Signal。

    对于实时信号,采用Queue管理已经挂起的重复信号。如下图所示(图片源自网络)。

                                

​​​​​​​6. 信号相关的系统调用

1)进程相关的接口

signal(),Linux早期的信号安装函数系统调用signal用来设定某个信号的处理方法

kill(),Linux早期的信号发送函数向进程发送一个信号

pause(),使调用的进程进入睡眠,直到接收到一个信号为止。

Alarm(),设置一个定时器,当定时器计时到达时,将发出一个信号给进程。

sigaction(),Linux新版本信号安装函数

sigqueue(),Linux新版本信号发送函数向进程发送一个信号

注意,当一个信号被发送到一个多线程的进程中(注意是发送到进程),内核会选择该进程中的任意线程来处理该信号。

2)线程相关的接口

a)信号掩码的操作

int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldest)

注意,当新线程创建后,它将继承创建它的线程的信号掩码。

b)发送信号到指定的线程

int pthread_kill(pthread_t thread, int sig)

int pthread_sigqueue(pthread_t thread, int sig, const union sigval value)

注意,pthread_sigqueue()函数是在glibc-2.11时加入的。它要求linux2.6.31,因为该版本提供了rt_tgsigqueueinfo()系统调用的。

​​​​​​​7. 其它

1)Sigaction常用的Flag

SA_NODEFER:当进程执行一个信号处理函数时,系统默认屏蔽相应的信号,即自动阻塞这个信号,直到处理程序结束,因此,所处理的信号的另一次出现,并不能中断信号处理程序,所以信号处理函数不必是可以重入的。如果用户设置了SA_NODEFER则不屏蔽该信号,存在重入的场景,如,在信号处理函数中发送相同的信号。

SA_RESTAR:使被信号打断的系统调用自动重新发起,系统默认不会重启被打断的系统调用。

A_RESETHAND:等同于SA_ONESHOT,注册的信号处理函数是一次性的,执行过后该信号的处理函数就变成了默认处理函数SIG_DFL。

2)网络编程相关的信号

     SIGPIPE:默认情况下,往一个读端关闭的管道或socket连接中写数据将引发SIGPIPE信号,SIGPIPE默认行为是结束进程,用户需要修改这样的默认行为

     SIGURG在linux环境下,内核通知应用程序带外数据到达主要有两种方法:一种是I/O复用技术,select等系统调用在接收到带外数据时将返回,并向应用程序报告socke上的异常事件,另一种方法就是SIGURG信号。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值