信号机制
信号机制是一种使用信号来进行进程之间传递消息的方法,信号的全称为软中断信号,简称软中断。信号的本质是软件层次上对中断的一种模拟(软中断)。它是一种异步通信的处理机制,事实上,进程并不知道信号何时到来。
在头文件<signal.h>中定义了64种信号,这些信号的名字都以SIG开头,且都被定义为正整数,称为信号编号。可以用“kill -l”查看信号的具体名称。
上图中编号为1~31的信号为早期Linux所支持的信号,是不可靠信号(非实时的),编号为34~63的信号时后来扩充的,称为可靠信号(实时信号)。不可靠信号与可靠信号的区别在于前者不支持排队(这意味着如果内核已经注册了这个信号,那么便不会再去注册,对于进程来说,便不会知道本次信号的发生),可能会造成信号丢失,而后者的注册机制是每收到一个可靠信号就会去注册这个信号,不会丢失。
信号的产生
Linux中的信号可以由以下几种方式产生:
·当用户按下某些终端按键后引发终端产生信号,如“Ctrl+C”等。
·硬件产生的异常信号,例如除数为0、无效的内存访问等。这种异常信号通常会由硬件检测并通知Linux内核,然后内核产生信号发送给相关进程。
·进程使用系统调用函数kill可以给一个进程或者进程组发送一个信号,此时发送和接收信号的进程/进程组的所有者必须相同。
·用户调用kill命令将信号发送给其他进程,如经常使用kill终止进程一样。
·当检测到某种软件条件已经发生,并将其通知有关进程的时候也会产生信号,例如SIGURG信号就是在接收到一个通过网络传送的外部数据时产生的。
信号处理方式
Linux的每一个信号都有一个缺省的动作,典型的缺省动作是终止进程,当一个信号到来的时候收到这个信号的进程会根据信号的具体情况提供一下三种不同的处理方式:
·对于需要处理的信号,指定处理函数,由该函数来处理。
·忽略某个信号,对该信号不做任何处理。
·对该信号的处理保留系统的默认值,这种缺省操作大多数使得进程终止,进程通过系统调用signal函数来指定进程对某个信号的处理行为。
信号处理过程
Linux内核给一个进程发送软中断的方法是:在进程所在的进程表项的信号域设置对应信号的位(在PCB中设置)。如果信号发送给一个正在睡眠的进程,如果进程的优先级是可中断的,则唤醒进程,否则仅设置PCB中信号域相应的位而不唤醒进程。一个进程检查是否收到信号的时机是:一个进程在即将从内核态切换到用户态时;或者再一个进程要进入或离开一个适当的低调度优先级睡眠状态时。
内核处理一个进程收到的软中断信号是在该进程的上下文中,因此进程必须处于运行状态。如果进程收到一个需要捕获的信号,会在进程从