SIGNAL - Linux手册页

时间:2019-08-20 18:02:02  来源:igfitidea点击:

Linux程序员手册 第7部分
更新日期: 2020-08-13

名称

信号-信号概述

说明

Linux支持POSIX可靠信号(以下称为"标准信号")和POSIX实时信号。

Signal dispositions

每个信号都有一个当前配置,该配置决定了当传递信号时过程如何表现。

下表的"操作"列中的条目为每个信号指定默认设置,如下所示:

Term
默认操作是终止该过程。
Ign
默认操作是忽略信号。
Core
默认操作是终止进程并转储核心(请参阅core(5))。
Stop
默认操作是停止该过程。
Cont
如果当前已停止,则默认操作是继续该过程。

进程可以使用sigaction(2)或signal(2)更改信号的布置。 (在建立信号处理程序时,后者的移植性较差;有关详细信息,请参见signal(2)。)使用这些系统调用,进程可以选择在传递信号时发生以下行为之一:执行默认操作;或者执行以下操作:忽略信号;或使用信号处理程序捕获信号,这是程序员定义的函数,在传递信号时会自动调用该函数。

默认情况下,在常规进程堆栈上调用信号处理程序。可以安排信号处理程序使用备用堆栈。请参见sigaltstack(2),以获取有关如何执行此操作以及何时使用它的讨论。

信号的配置是每个进程的属性:在多线程应用程序中,特定信号的配置对于所有线程都是相同的。

通过fork(2)创建的子级继承其父级信号处置的副本。在execve(2)期间,已处理信号的处理将重置为默认值;被忽略信号的配置保持不变。

Sending a signal

以下系统调用和库函数允许调用方发送信号:

raise(3)
向调用线程发送信号。
kill(2)
向指定的进程,指定的进程组的所有成员或系统上的所有进程发送信号。
killpg(3)
向指定过程组的所有成员发送信号。
pthread_kill(3)
在与调用者相同的过程中将信号发送到指定的POSIX线程。
tgkill(2)
将信号发送到特定进程中的指定线程。 (这是用于实现pthread_kill(3)的系统调用。)
sigqueue(3)
将带有随附数据的实时信号发送到指定的进程。

Waiting for a signal to be caught

以下系统调用暂停执行调用线程,直到捕获到信号(或未处理的信号终止进程)为止:

pause(2)
暂停执行,直到捕获到任何信号为止。
sigsuspend(2)
临时更改信号掩码(请参阅下文)并中止执行,直到捕获到未屏蔽的信号之一。

Synchronously accepting a signal

与其通过信号处理程序异步捕获信号,不如同步接收信号,即阻塞执行直到传递信号为止,此时内核将有关信号的信息返回给调用方。有两种一般的方法可以做到这一点:

*
sigwaitinfo(2),sigtimedwait(2)和sigwait(3)暂停执行,直到传递了指定集中的信号之一。这些调用中的每一个都返回有关传递信号的信息。
*
signalfd(2)返回一个文件描述符,该文件描述符可用于读取有关传递给调用方的信号的信息。从此文件描述符进行的每个read(2)都会阻塞,直到在signalfd(2)调用中指定的集合中的信号之一传递给调用者为止。 read(2)返回的缓冲区包含描述信号的结构。

Signal mask and pending signals

信号可能会被阻塞,这意味着直到以后将其解除阻塞后,信号才会被传递。在信号生成和交付之间,信号被认为是未决的。

进程中的每个线程都有一个独立的信号掩码,该掩码指示该线程当前正在阻塞的信号集。线程可以使用pthread_sigmask(3)操纵其信号掩码。在传统的单线程应用程序中,sigprocmask(2)可用于操纵信号掩码。

通过fork(2)创建的子级继承其父级信号掩码的副本;信号掩码在execve(2)中保留。

信号可以是过程控制或线程控制的。过程控制信号是针对整个过程的信号(因此待定)。信号可能是过程控制的,这是因为它是由内核出于硬件异常以外的原因生成的,或者因为它是使用kill(2)或sigqueue(3)发送的。线程定向信号是针对特定线程的信号。信号可能是线程定向的,因为它是由于执行触发硬件异常的特定机器语言指令而产生的(例如,SIGSEGV用于无效的存储器访问,而SIGFPE用于数学错误),或者因为它是针对性的在特定线程中使用tgkill(2)或pthread_kill(3)之类的接口。

可以将过程控制信号传递到当前未阻塞信号的任何一个线程。如果多个线程中的信号畅通无阻,则内核选择一个任意线程来将信号传递到该线程。

线程可以使用sigpending(2)获得当前有待处理的信号集。该集合将由未决的过程控制信号集合和调用线程的未决信号集合的并集组成。

通过fork(2)创建的子代最初具有一个空的挂起信号集;待处理信号集在execve(2)中保留。

Standard signals

Linux支持下面列出的标准信号。该表的第二列指示指定信号的标准(如果有):" P1990"指示该信号在原始POSIX.1-1990标准中进行了描述; " P2001"表示信号已添加到SUSv2和POSIX.1-2001中。

SignalStandardActionComment
SIGALRMP1990TermTimer signal from alarm(2)
SIGBUSP2001CoreBus error (bad memory access)
SIGCHLDP1990IgnChild stopped or terminated
SIGCLD-IgnA synonym for SIGCHLD
SIGCONTP1990ContContinue if stopped
SIGEMT-TermEmulator trap
SIGFPEP1990CoreFloating-point exception
SIGHUPP1990TermHangup detected on controlling terminal
or death of controlling process
SIGILLP1990CoreIllegal Instruction
SIGINFO-A synonym for SIGPWR
SIGINTP1990TermInterrupt from keyboard
SIGIO-TermI/O now possible (4.2BSD)
SIGIOT-CoreIOT trap. A synonym for SIGABRT
SIGKILLP1990TermKill signal
SIGLOST-TermFile lock lost (unused)
SIGPIPEP1990TermBroken pipe: write to pipe with no
readers; see pipe(7)
SIGPOLLP2001TermPollable event (Sys V);
synonym for SIGIO
SIGPROFP2001TermProfiling timer expired
SIGPWR-TermPower failure (System V)
SIGQUITP1990CoreQuit from keyboard
SIGSEGVP1990CoreInvalid memory reference
SIGSTKFLT-TermStack fault on coprocessor (unused)
SIGSTOPP1990StopStop process
SIGTSTPP1990StopStop typed at terminal
SIGSYSP2001CoreBad system call (SVr4);
see also seccomp(2)
SIGTERMP1990TermTermination signal
SIGTRAPP2001CoreTrace/breakpoint trap
SIGTTINP1990StopTerminal input for background process
SIGTTOUP1990StopTerminal output for background process
SIGUNUSED-CoreSynonymous with SIGSYS
SIGURGP2001IgnUrgent condition on socket (4.2BSD)
SIGUSR1P1990TermUser-defined signal 1
SIGUSR2P1990TermUser-defined signal 2
SIGVTALRMP2001TermVirtual alarm clock (4.2BSD)
SIGXCPUP2001CoreCPU time limit exceeded (4.2BSD);
see setrlimit(2)
SIGXFSZP2001CoreFile size limit exceeded (4.2BSD);
see setrlimit(2)
SIGWINCH-IgnWindow resize signal (4.3BSD, Sun)

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

在Linux 2.2之前(包括Linux 2.2),SIGSYSSIGXCPU,SIGXFSZ和(在SPARC和MIPS以外的体系结构上)SIGBUS的默认行为是终止进程(不进行核心转储)。 (在其他一些UNIX系统上,SIGXCPU和SIGXFSZ的默认操作是在没有核心转储的情况下终止进程。)Linux 2.4符合POSIX.1-2001对这些信号的要求,以核心转储来终止进程。

在POSIX.1-2001中未指定SIGEMT,但在大多数其他UNIX系统上仍会显示SIGEMT,在该系统中,其默认操作通常是使用核心转储来终止进程。

默认情况下,SIGPWR(在POSIX.1-2001中未指定)通常在出现它的那些其他UNIX系统上被忽略。

在其他几个UNIX系统上,默认情况下会忽略SIGIO(在POSIX.1-2001中未指定)。

Queueing and delivery semantics for standard signals

如果有多个标准信号正在等待处理,则信号的传递顺序不确定。

标准信号不排队。如果在阻塞该信号的同时生成了一个标准信号的多个实例,则仅将信号的一个实例标记为未决(并且在解除阻塞时,该信号将仅发送一次)。在标准信号已经挂起的情况下,与该信号关联的siginfo_t结构(请参见sigaction(2))在同一信号的后续实例到达时不会被覆盖。因此,该过程将接收与信号的第一实例相关联的信息。

Signal numbering for standard signals

下表列出了每个信号的数值。如表所示,许多信号在不同的架构上具有不同的数值。每个表行中的第一个数字值表示x86,ARM和大多数其他体系结构上的信号编号;第二个值用于Alpha和SPARC;第三是针对MIPS;最后是巴黎。破折号(-)表示相应的体系结构上不存在信号。

Signalx86/ARMAlpha/MIPSPARISCNotes
most othersSPARC
SIGINT2222
SIGQUIT3333
SIGILL4444
SIGTRAP5555
SIGABRT6666
SIGIOT6666
SIGBUS7101010
SIGEMT-77-
SIGFPE8888
SIGKILL9999
SIGUSR110301616
SIGSEGV11111111
SIGUSR212311717
SIGPIPE13131313
SIGALRM14141414
SIGTERM15151515
SIGSTKFLT16--7
SIGCHLD17201818
SIGCLD--18-
SIGCONT18192526
SIGSTOP19172324
SIGTSTP20182425
SIGTTIN21212627
SIGTTOU22222728
SIGURG23162129
SIGXCPU24243012
SIGXFSZ25253130
SIGVTALRM26262820
SIGPROF27272921
SIGWINCH28282023
SIGIO29232222
SIGPOLLSame as SIGIO
SIGPWR3029/-1919
SIGINFO-29/---
SIGLOST--/29--
SIGSYS31121231
SIGUNUSED31--31

请注意以下几点:

*
在定义的地方,SIGUNUSED与SIGSYS是同义词。从glibc 2.26开始,不再在任何体系结构上定义SIGUNUSED。
*
信号29在Alpha上是SIGINFO / SIGPWR(相同值的同义词),在SPARC上是SIGLOST。

Real-time signals

从2.2版开始,Linux支持最初在POSIX.1b实时扩展中定义的实时信号(现在包括在POSIX.1-2001中)。支持的实时信号范围由宏SIGRTMIN和SIGRTMAX定义。 POSIX.1-2001要求实现至少支持_POSIX_RTSIG_MAX(8)个实时信号。

Linux内核支持33种不同的实时信号,范围从32到64。但是,glibc POSIX线程实现内部使用两个(对于NPTL)或三个(对于LinuxThreads)实时信号(请参阅pthreads(7))。 ,并适当调整SIGRTMIN的值(至34或35)。因为可用的实时信号的范围根据glibc线程实现的不同而有所变化(并且这种变化可能会在运行时根据可用的内核和glibc发生),并且实际上,实时信号的范围在UNIX系统上也有所不同,不要使用硬编码数字引用实时信号,而应该使用SIGRTMIN + n引用实时信号,并包括适当的(运行时)检查,以确保SIGRTMIN + n不超过SIGRTMAX。

与标准信号不同,实时信号没有预定义的含义:整个实时信号集可用于应用程序定义的目的。

未处理的实时信号的默认操作是终止接收过程。

实时信号的特征如下:

1.
实时信号的多个实例可以排队。相比之下,如果在当前阻塞标准信号的情况下传递了该信号的多个实例,则仅将一个实例排队。
2.
如果使用sigqueue(3)发送信号,则可以将伴随值(整数或指针)与信号一起发送。如果接收进程使用到sigaction(2)的SA_SIGINFO标志为此信号建立了处理程序,则接收进程可以通过siginfo_t结构的si_value字段(作为第二个参数传递给处理程序)获取此数据。此外,此结构的si_pid和si_uid字段可用于获取发送信号的进程的PID和实际用户ID。
3.
实时信号以保证的顺序交付。相同类型的多个实时信号按其发送顺序进行传递。如果将不同的实时信号发送到进程,则从编号最小的信号开始传递它们。 (即,编号较低的信号具有最高优先级。)相反,如果有多个标准信号等待处理,则未指定它们的传送顺序。

如果标准信号和实时信号都在等待处理,则POSIX会保留未指定的优先顺序。在这种情况下,Linux与许多其他实现一样,优先考虑标准信号。

根据POSIX,实现应至少允许将_POSIX_SIGQUEUE_MAX(32)实时信号排队到进程中。但是,Linux的处理方式有所不同。在2.6.7(含)以下的内核中,Linux对所有进程的排队实时信号数量施加了系统范围的限制。可以通过/ proc / sys / kernel / rtsig-max文件查看和(有特权)更改此限制。可以使用一个相关的文件/ proc / sys / kernel / rtsig-nr来查找当前排队了多少个实时信号。在Linux 2.6.8中,这些/ proc接口被RLIMIT_SIGPENDING资源限制所取代,该资源限制为队列信号指定了每个用户的限制;有关更多详细信息,请参见setrlimit(2)。

实时信号的添加要求将信号集结构(sigset_t)从32位扩展到64位。因此,各种系统调用被支持较大信号集的新系统调用所取代。旧的和新的系统调用如下:

Linux 2.0 and earlierLinux 2.2 and later
sigaction(2)rt_sigaction(2)
sigpending(2)rt_sigpending(2)
sigprocmask(2)rt_sigprocmask(2)
sigreturn(2)rt_sigreturn(2)
sigsuspend(2)rt_sigsuspend(2)
sigtimedwait(2)rt_sigtimedwait(2)

Interruption of system calls and library functions by signal handlers

如果在阻止系统调用或库函数调用的同时调用了信号处理程序,则可以:

*
信号处理程序返回后,呼叫将自动重新启动;要么
*
呼叫失败,并显示错误EINTR。

发生这两种行为中的哪一种取决于接口,以及是否使用SA_RESTART标志建立了信号处理程序(请参见sigaction(2))。各个UNIX系统上的详细信息有所不同。下面是Linux的详细信息。

如果信号处理程序中断了对以下接口之一的阻塞调用,则如果使用了SA_RESTART标志,则在信号处理程序返回后,该调用将自动重新启动;否则,将重新启动该调用。否则,调用将失败,并显示错误EINTR

*
在"慢速"设备上调用read(2),readv(2),write(2),writev(2)和ioctl(2)。 "慢速"设备是指I / O调用可能无限期阻塞的设备,例如终端,管道或套接字。如果在速度较慢的设备上的I / O调用在被信号处理程序中断之前已经传输了一些数据,则该调用将返回成功状态(通常为传输的字节数)。请注意,根据此定义,(本地)磁盘不是慢速设备。磁盘设备上的I / O操作不会被信号中断。
*
open(2),如果它可以阻塞(例如,在打开FIFO时;请参见fifo(7))。
*
wait(2),wait3(2),wait4(2),waitid(2)和waitpid(2)。
*
套接字接口:accept(2),connect(2),recv(2),recvfrom(2),recvmmsg(2),recvmsg(2),send(2),sendto(2)和sendmsg(2),除非套接字上已设置超时(请参见下文)。
*
文件锁定接口:flock(2)以及fcntl(2)的F_SETLKW和F_OFD_SETLKW操作
*
POSIX消息队列接口:mq_receive(3),mq_timedreceive(3),mq_send(3)和mq_timedsend(3)。
*
futex(2)FUTEX_WAIT(从Linux 2.6.22开始;以前,始终因EINTR失败)。
*
getrandom(2)。
*
pthread_mutex_lock(3),pthread_cond_wait(3)和相关的API。
*
futex(2)FUTEX_WAIT_BITSET。
*
POSIX信号量接口:sem_wait(3)和sem_timedwait(3)(从Linux 2.6.22开始;以前,始终因EINTR而失败)。
*
inotify(7)文件描述符读取(2)(从Linux 3.8开始;以前,始终因EINTR失败)。

不管使用SA_RESTART,以下接口在被信号处理程序中断后都不会重新启动;当被信号处理程序中断时,它们总是失败并显示错误EINTR

*
当使用setsockopt(2)在套接字上设置了超时(SO_RCVTIMEO)时,即为"输入"套接字接口:accept(2),recv(2),recvfrom(2),recvmmsg(2)(也具有非NULL)超时参数)和recvmsg(2)。
*
使用setsockopt(2)在套接字上设置超时(SO_RCVTIMEO)时,将使用"输出"套接字接口:connect(2),send(2),sendto(2)和sendmsg(2)。
*
用于等待信号的接口:pause(2),sigsuspend(2),sigtimedwait(2)和sigwaitinfo(2)。
*
文件描述符多路复用接口:epoll_wait(2),epoll_pwait(2),poll(2),ppoll(2),select(2)和pselect(2)。
*
系统V IPC接口:msgrcv(2),msgsnd(2),semop(2)和semtimedop(2)。
*
睡眠接口:clock_nanosleep(2),nanosleep(2)和usleep(3)。
*
io_getevents(2)。

如果被处理程序中断,sleep(3)函数也永远不会重新启动,但会返回成功:剩余的睡眠秒数。

Interruption of system calls and library functions by stop signals

在Linux上,即使没有信号处理程序,某些进程的阻塞接口也可能在停止信号之一使进程停止然后通过SIGCONT恢复后,由于错误EINTR而失败。此行为不受POSIX.1认可,在其他系统上也不会发生。

显示此行为的Linux接口是:

*
当使用setsockopt(2)在套接字上设置了超时(SO_RCVTIMEO)时,即为"输入"套接字接口:accept(2),recv(2),recvfrom(2),recvmmsg(2)(也具有非NULL)超时参数)和recvmsg(2)。
*
如果使用setockopt(2)在套接字上设置了超时(SO_RCVTIMEO),则为"输出"套接字接口:connect(2),send(2),sendto(2)和sendmsg(2),如果发送超时( SO_SNDTIMEO)已设置。
*
epoll_wait(2),epoll_pwait(2)。
*
semop(2),semtimedop(2)。
*
sigtimedwait(2),sigwaitinfo(2)。
*
Linux 3.7和更早版本:从inotify(7)文件描述符读取(2)
*
Linux 2.6.21和更早版本:futex(2)FUTEX_WAITsem_timedwait(3),sem_wait(3)。
*
Linux 2.6.8和更早版本:msgrcv(2),msgsnd(2)。
*
Linux 2.4和更早版本:nanosleep(2)。

遵循规范

POSIX.1,除非另有说明。

备注

有关异步信号安全功能的讨论,请参见signal-safety(7)。

/ proc / [pid] / task / [tid] / status文件包含各种字段,这些字段显示线程正在阻塞(SigBlk),捕获(SigCgt)或忽略(SigIgn)的信号。 (捕获或忽略的信号集在一个进程中的所有线程上都将是相同的。)其他字段显示定向到线程(SigPnd)的未决信号集以及定向到该信号的未决信号集。整个过程(ShdPnd)。 / proc / [pid] / status中的相应字段显示了主线程的信息。有关更多详细信息,请参见proc(5)。

BUGS

由于硬件异常,可以传递六个信号:SIGBUSSIGEMTSIGFPESIGILL,SIGSEGV和SIGTRAP。对于任何给定的硬件异常,这些信号中的哪个信号都没有记录,并且并不总是有意义。

例如,导致在一个CPU体系结构上传递SIGSEGV的无效内存访问可能会导致在另一体系结构上传递SIGBUS,反之亦然。

再举一个例子,将x86 int指令与禁止的参数(3或128以外的任何数字)一起使用会导致SIGSEGV的传递,即使SIGILL更有意义,因为CPU会向内核报告禁止的操作。

另外参见

kill(1),clone(2),getrlimit(2),kill(2),pidfd_send_signal(2),restart_syscall(2),rt_sigqueueinfo(2),setitimer(2),setrlimit(2),sgetmask(2), sigaction(2),sigaltstack(2),signal(2),signalfd(2),sigpending(2),sigprocmask(2),sigreturn(2),sigsuspend(2),sigwaitinfo(2),abort(3), bsd_signal(3),killpg(3),longjmp(3),pthread_sigqueue(3),raise(3),sigqueue(3),sigset(3),sigsetops(3),sigvec(3),sigwait(3), strsignal(3),sysv_signal(3),core(5),proc(5),nptl(7),pthreads(7),sigevent(7)

出版信息

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