好好活就是有意义的事,有意义的事就是好好活
Linux手册翻译  signal(2)
Linux手册翻译 signal(2)

Linux手册翻译 signal(2)

https://man7.org/linux/man-pages/man2/signal.2.html

\color{#A00000}{NAME}
signal - ANSI C signal handling
\color{#A00000}{SYNOPSIS}
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
\color{#A00000}{DESCRIPTION}

警告: signal()的行为因UNIX版本而已, 并且历史上不同的Linux版本也会有送不同, 细节参阅NotesPortability. 推荐使用sigreturn(2).

signal() 将信号signum的disposition设置为handle, handle 可以是 SIG_IGNSIG_DFL 或程序员定义的函数(信号处理程序)的地址.

如果将信号signum传递给进程,则会发生以下情况之一:

  • 如果disposition设置为 SIG_IGN,则忽略该信号;
  • 如果disposition设置为 SIG_DFL,则执行与信号关联的默认操作(请参阅 signal(7));
  • 如果disposition设置为函数,则首先disposition被重置为 SIG_DFL,或者信号被阻塞(参见Notes中的Portability),然后使用参数 signum 调用handler。 如果处理程序的调用导致信号被阻塞,则信号在从处理程序返回时被解除阻塞。换句话说, 第三种处理方式, 在处理信号的过程中, 又有信号到达, 要么执行默认的策略, 要么将其阻塞.

信号 SIGKILL SIGSTOP 不能被捕获或忽略。

\color{#A00000}{RETURN VALUE}

signa() 成功时返回先前的信号处理函数( sighandler_t ); 失败时将返回SIG_ERR, 同时设置errno.

\color{#A00000}{ERRORS}
EINVAL signum is invalid.
\color{#A00000}{CONFORMING TO}
POSIX.1-2001, POSIX.1-2008, C89, C99.
\color{#A00000}{NOTES}

未指定多线程进程中 signal() 的效果。

根据 POSIX,进程在忽略不是由 kill(2) 或 raise(3) 生成的 SIGFPE、SIGILL 或 SIGSEGV 信号后,其行为是不确定的。整数除以零有未定义的结果, 在某些架构上,它会生成一个 SIGFPE 信号. (同样将最大负整数除以 -1 可能会生成 SIGFPE.) 忽略此信号可能会导致无限循环。

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

The use of sighandler_t is a GNU extension, exposed if _GNU_SOURCE is defined; glibc also defines (the BSD-derived) sig_t if _BSD_SOURCE (glibc 2.19 and earlier) or _DEFAULT_SOURCE (glibc 2.19 and later) is defined. Without use of such a type, the declaration of signal() is the somewhat harder to read:

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

The only portable use of signal() is to set a signal’s disposition to SIG_DFL or SIG_IGN. The semantics when using signal() to establish a signal handler vary across systems (and POSIX.1 explicitly permits this variation); do not use it for this purpose.

POSIX.1 solved the portability mess by specifying sigaction(2), which provides explicit control of the semantics when a signal handler is invoked; use that interface instead of signal().

In the original UNIX systems, when a handler that was established using signal() was invoked by the delivery of a signal, the disposition of the signal would be reset to SIG_DFL, and the system did not block delivery of further instances of the signal. This is equivalent to calling sigaction(2) with the following flags:

sa.sa_flags = SA_RESETHAND | SA_NODEFER;

System V also provides these semantics for signal(). This was bad because the signal might be delivered again before the handler had a chance to reestablish itself. Furthermore, rapid deliveries of the same signal could result in recursive invocations of the handler.

BSD improved on this situation, but unfortunately also changed the semantics of the existing signal() interface while doing so. On BSD, when a signal handler is invoked, the signal disposition is not reset, and further instances of the signal are blocked from being delivered while the handler is executing. Furthermore, certain blocking system calls are automatically restarted if interrupted by a signal handler (see signal(7)). The BSD semantics are equivalent to calling sigaction(2) with the following flags:

sa.sa_flags = SA_RESTART;

The situation on Linux is as follows:

  • The kernel’s signal() system call provides System V semantics.
  • By default, in glibc 2 and later, the signal() wrapper function does not invoke the kernel system call. Instead, it calls sigaction(2) using flags that supply BSD semantics. This default behavior is provided as long as a suitable feature test macro is defined: _BSD_SOURCE on glibc 2.19 and earlier or _DEFAULT_SO

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注