语法

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

遵循规范

POSIX.1-2001,POSIX.1-2008,C89,C99。

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/

返回值

signal()返回信号处理程序的前一个值,如果出错则返回SIG_ERR。如果发生错误,则设置errno来指示原因。

错误说明

EINVAL
签名无效。

说明

signal()的行为在UNIX版本之间有所不同,并且在历史上在Linux的不同版本之间也有所不同。避免使用它:改为使用sigaction(2)。请参阅下面的可移植性。

signal()将信号符号的设置设置为处理程序,该处理程序可以是SIG_IGN,SIG_DFL或程序员定义的函数的地址("信号处理程序")。

如果信号信号传递到该进程,则发生以下情况之一:

*
如果将处置设置为SIG_IGN,则忽略该信号。
*
如果将处置设置为SIG_DFL,则会发生与信号关联的默认操作(请参见signal(7))。
*
如果将处置设置为函数,则首先将处置重置为SIG_DFL,或者阻止信号(请参见下面的可移植性),然后使用参数signum调用处理程序。如果调用处理程序导致信号被阻塞,则从处理程序返回后,信号将被解除阻塞。

无法捕获或忽略信号SIGKILL和SIGSTOP。

另外参见

kill(1),alarm(2),kill(2),pause(2),sigaction(2),signalfd(2),sigpending(2),sigprocmask(2),sigsuspend(2),bsd_signal(3), killpg(3),raise(3),soirnterrupt(3),sigqueue(3),sigsetops(3),sigvec(3),sysv_signal(3),signal(7)

名称

signal-ANSI C信号处理

SIGNAL - Linux手册页

Linux程序员手册 第2部分
更新日期: 2017-09-15

备注

在多线程进程中,signal()的作用是不确定的。

根据POSIX,在忽略不由kill(2)或raise(3)生成的SIGFPE,SoirLL或SIGSEGV信号之后,进程的行为是不确定的。整数除以零将产生不确定的结果。在某些架构上,它将生成SIGFPE信号。 (也将最负的整数除以-1可能会生成SIGFPE。)忽略此信号可能会导致无限循环。

有关处置SIGCHLD设置为SIG_IGN时会发生的情况的详细信息,请参见sigaction(2)。

有关可以从信号处理程序内部安全调用的异步信号安全函数的列表,请参见signal-safety(7)。

sighandler_t的使用是GNU扩展,如果定义了_GNU_SOURCE,则将公开。如果定义了_BSD_SOURCE(glibc 2.19和更低版本)或_DEFAULT_SOURCE(glibc 2.19和更高版本),则glibc还将定义(BSD派生的)sig_t。如果不使用这样的类型,那么signal()的声明将更难读取:

void ( *signal(int signum, void (*handler)(int)) ) (int);

Portability

signal()的唯一可移植用法是将信号的处理方式设置为SIG_DFL或SIG_IGN。使用signal()建立信号处理程序时的语义在系统之间有所不同(并且POSIX.1明确允许这种变化);请勿将其用于此目的。

POSIX.1通过指定sigaction(2)解决了可移植性问题,当调用信号处理程序时,sigaction(2)提供了对语义的显式控制。使用该接口而不是signal()。

在原始的UNIX系统中,当通过信号的传递调用使用signal()建立的处理程序时,信号的处置将被重置为SIG_DFL,并且系统没有阻止信号的其他实例的传递。这等效于使用以下标志调用sigaction(2):

sa.sa_flags = SA_RESETHAND | SA_NODEFER;

System V还为signal()提供了这些语义。这很糟糕,因为信号可能在处理程序有机会重新建立自身之前再次传递。此外,相同信号的快速传递可能导致处理程序的递归调用。

BSD在这种情况下进行了改进,但不幸的是,这样做也改变了现有signal()接口的语义。在BSD上,当调用信号处理程序时,不会重置信号处理,并且在执行处理程序时阻止传递其他信号实例。此外,如果某些阻塞的系统调用被信号处理程序中断,则会自动重新启动(请参见signal(7))。 BSD语义等效于使用以下标志调用sigaction(2):

sa.sa_flags = SA_RESTART;

Linux上的情况如下:

*
内核的signal()系统调用提供System V语义。
*
默认情况下,在glibc 2和更高版本中,signal()包装函数不会调用内核系统调用。相反,它使用提供BSD语义的标志调用sigaction(2)。只要定义了合适的功能测试宏,就会提供此默认行为:在glibc 2.19和更低版本中为_BSD_SOURCE或在glibc 2.19和更高版本中为_DEFAULT_SOURCE。 (默认情况下,这些宏已定义;有关详细信息,请参见feature_test_macros(7)。)如果未定义这样的功能测试宏,那么signal()将提供System V语义。
日期:2019-08-20 17:59:26 来源:oir作者:oir