信号 (计算机科学)

维基百科,自由的百科全书
跳转至: 导航搜索

在计算机科学中,信号英语Signals)是Unix类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。

发送信号[编辑]

  • 在一个运行的程序的控制终端键入特定的组合键可以向它发送某些信号:
    • Ctrl-C发送INT信号(SIGINT);默认情况下,这会导致进程终止。
    • Ctrl-Z发送TSTP信号(SIGTSTP);默认情况下,这会导致进程挂起
    • Ctrl-\发送QUIT信号(SIGQUIT);默认情况下,这会导致进程终止并且将内存中的信息转储到硬盘(核心转储)。
    • (这些组合键可以通过stty命令来修改。)
  • kill()系统调用会在权限允许的情况下向进程发送特定的信号,类似地,kill命令允许用户向进程发送信号。raise(3)库函数可以将特定信号发送给当前进程。
  • 像除数为零、断错误这些异常也会产生信号(这里分别是SIGFPESIGSEGV,默认都会导致进程终止和核心转储).
  • 内核可以向进程发送信号以告知它一个事件发生了。例如当进程将数据写入一个已经被关闭的管道是将会收到SIGPIPE信号,默认情况下会使进程关闭。

处理信号[编辑]

信号处理函数可以通过signal()系统调用来设置。如果没有为一个信号设置对应的处理函数,就会使用默认的处理函数,否则信号就被进程截获并调用相应的处理函数。在没有处理函数的情况下,程序可以指定两种行为:忽略这个信号(SIG_IGN)或者用默认的处理函数(SIG_DFL)。但是有两个信号是无法被截获并处理的:SIGKILLSIGSTOP

风险[编辑]

因为竞态条件的存在,信号的处理是有弱点的。因为信号是异步的,所以在处理一个信号的过程中,进程可能收到另一个信号(甚至是相同的信号)。sigprocmask()系统调用可以用来阻塞和恢复信号的传递。信号可以造成进程中系统调用的中断,并在信号处理完后重新开始未完成的系统调用。信号处理函数应该没有任何不想要的副作用,比如,errno的改变、信号掩码的改变、信号处理方法的改变,以及其他全局进程性质的改变。在信号处理函数内使用不可重入函数,如mallocprintf,也是不安全的。

与硬件异常的关系[编辑]

进程的运行也可能导致硬件异常,例如,将一个数除以零,或者出现TLB不命中。在类Unix系统中,这会自动运行内核的异常处理程序。对于某些异常如页缺失,内核有足够的信息来处理完并恢复进程的运行。但是对于另外一些异常,内核不能处理而只能通过发送信号把异常交给进程自己处理。例如在x86架构的CPU上,如果一个进程尝试将一个数除以零,将会产生divide error异常,并使内核向出错的进程发送SIGFPE信号。相似地,如果一个进程尝试访问虚拟地址空间以外的内存,内核将向进程发送SIGSEGV信号。异常与信号的具体对应关系在不同的CPU架构上是不同的。

信号列表[编辑]

单一UNIX规范规定了在<signal.h>中定义的信号有:

备注:打星号的部分表示这是X/Open System Interfaces (XSI)扩充的部分。使用引号的文字是引用自SUS[1]

参见[编辑]

外部链接[编辑]