signal

设置中断信号处理。

重要

不要使用此方法关闭 Microsoft Store 应用,除非在测试或调试方案中。 根据 Microsoft Store 策略,禁止以编程或 UI 方式关闭 Store 应用。 有关详细信息,请参阅 UWP 应用生命周期

语法

void __cdecl *signal(int sig, int (*func)(int, int));

参数

sig
信号值。

func
第二个参数是指向要执行的函数的指针。 第一个参数是信号值,第二个参数是可在第一个参数为SIGFPE时使用的子代码。

返回值

signal 返回与给定信号关联的函数的上一个值。 例如,如果 func 的上一个值是 SIG_IGN,则返回值也是 SIG_IGNSIG_ERR 的返回值表示错误;在这种情况下,errno 将设置为 EINVAL

有关返回代码的详细信息,请参阅 errno_doserrno_sys_errlist_sys_nerr

注解

利用 signal 函数,进程可以从几种方法中选择一种来处理来自操作系统的中断信号。 sig 参数是 signal 响应的中断;它必须是在 SIGNAL.H 中定义的以下清单常量之一。

sig 说明
SIGABRT 异常终止
SIGFPE 浮点错误
SIGILL 非法指令
SIGINT Ctrl+C 信号
SIGSEGV 非法存储区访问
SIGTERM 终止请求

如果sig不是上述值之一,会调用无效参数处理程序,如参数验证中所定义。 如果允许执行继续,则该函数将 errno 设置为 EINVAL 并返回 SIG_ERR

默认情况下,无论 signal 的值如何,sig 都将终止调用程序并显示退出代码 3。

注意

任何 Win32 应用程序都不支持 SIGINT。 当 Ctrl+C 中断发生时,Win32 操作系统将专门生成新的线程来处理中断。 这可能导致单线程应用程序(如 UNIX 中的此类应用程序)变成多线程应用程序并导致意外行为。

func参数是你编写的信号处理程序的地址,或者预定义信号操作常量SIG_DFLSIG_IGN之一(也在 SIGNAL.H 中定义)的地址。 如果func是函数,它会作为给定信号的信号处理程序安装。 该信号处理程序的原型需要一个 sig 类型的形参 int。 当发生中断时,操作系统将通过 sig 提供实参;此参数是生成中断的信号。 因此,您可以在信号处理程序中使用六个清单常量(在前面的表中列出)来确定发生了哪种中断并采取相应措施。 例如,您可以调用 signal 两次来将同一处理程序分配给两个不同的信号,然后测试处理程序中的 sig 参数以基于收到的信号采取不同的措施。

如果要测试浮点异常 (SIGFPE),func会指向采用可选的第二个参数的函数,此参数是在FLOAT.H中定义的采用FPE_xxx形式的几个清单常量之一。 当SIGFPE信号发生时,可以测试第二个参数的值以确定浮点异常的类型,然后采取相应措施。 此参数及其可能的值是 Microsoft 扩展名。

对于浮点异常,在接收到信号时不会重置func的值。 若要从浮点异常恢复,请使用 try/except 子句包围浮点运算。 将 setjmplongjmp 一起使用也能恢复。 在任一情况下,调用进程都会继续执行,并保留未定义的进程的浮点状态。

如果信号处理程序返回,调用进程将在收到断点信号后立即继续执行,不考虑信号或操作模式的类型。

在执行指定的函数前,func 的值将设置为 SIG_DFL。 下一个中断信号将按照为 SIG_DFL 描述的方法处理,除非对 signal 的干预调用另行指定。 您可以使用此功能在所调用的函数中重置信号。

由于信号处理程序例程通常在中断发生时异步调用,当运行时操作不完整且处于未知状态时,信号处理程序可能受到控制。 以下列表汇总了一些限制,用来确定您可在信号处理程序例程中使用的函数。

  • 不要发出低级别或STDIO.H I/O 例程(例如,printffread)。

  • 不要调用堆例程或任何使用堆例程的例程(例如,malloc_strdup_putenv)。 有关详细信息,请参阅 malloc

  • 不要使用生成系统调用的任何函数(例如,_getcwdtime)。

  • 不要使用longjmp,除非中断是由浮点异常导致的(即,sigSIGFPE)。 在这种情况下,首先应使用对 _fpreset 的调用重新初始化浮点程序包。

  • 不要使用任何重叠例程。

如果某个程序要使用函数捕获SIGFPE异常,该程序必须包含浮点代码。 如果程序没有浮点代码并且需要运行库的信号处理代码,只需声明一个可变双精度值并将其初始化为零:

volatile double d = 0.0f;

SIGILLSIGTERM信号不会在 Windows 下产生。 包含它们是为了实现 ANSI 兼容。 因此,可以使用 signal 为这些信号设置信号处理程序,还可以通过调用 raise 显式生成这些信号。

信号设置不会保存在通过调用_exec_spawn函数生成的生成进程中。 信号设置在新进程中将重置为默认值。

要求

例程 必需的标头
signal <signal.h>

有关兼容性的详细信息,请参阅 兼容性

示例

以下示例演示如何使用 signal 将一些自定义行为添加到 SIGABRT 信号。 有关中止行为的详细信息,请参阅_set_abort_behavior

// crt_signal.c
// compile with: /EHsc /W4
// Use signal to attach a signal handler to the abort routine
#include <stdlib.h>
#include <signal.h>

void SignalHandler(int signal)
{
    if (signal == SIGABRT) {
        // abort signal handler code
    } else {
        // ...
    }
}

int main()
{
    typedef void (*SignalHandlerPointer)(int);

    SignalHandlerPointer previousHandler;
    previousHandler = signal(SIGABRT, SignalHandler);

    abort();
}

输出取决于使用的运行时版本、应用是控制台还是 Windows 应用,以及 Windows 注册表设置。 对于控制台应用,可能会将以下类似消息发送到 stderr:

Debug Error!

Program: c:\Projects\crt_signal\Debug\crt_signal.exe

R6010

- abort() has been called

另请参阅

进程和环境控制
abort
_exec_wexec 函数
exit, _Exit, _exit
_fpreset
_spawn_wspawn 函数