设置中断信号处理。
重要
不要使用此方法关闭 Microsoft Store 应用,除非在测试或调试方案中。 根据 Microsoft Store 策略,禁止以编程或 UI 方式关闭 Store 应用。 有关详细信息,请参阅 UWP 应用生命周期。
语法
void __cdecl *signal(int sig, int (*func)(int, int));
参数
sig
信号值。
func
第二个参数是指向要执行的函数的指针。 第一个参数是信号值,第二个参数是可在第一个参数为SIGFPE时使用的子代码。
返回值
signal 返回与给定信号关联的函数的上一个值。 例如,如果 func 的上一个值是 SIG_IGN,则返回值也是 SIG_IGN。 SIG_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_DFL,或在 SIG_IGNSIGNAL.H 中定义。 如果func是函数,它会作为给定信号的信号处理程序安装。 该信号处理程序的原型需要一个 sig 类型的形参 int。 当发生中断时,操作系统将通过 sig 提供实参;此参数是生成中断的信号。 因此,您可以在信号处理程序中使用六个清单常量(在前面的表中列出)来确定发生了哪种中断并采取相应措施。 例如,您可以调用 signal 两次来将同一处理程序分配给两个不同的信号,然后测试处理程序中的 sig 参数以基于收到的信号采取不同的措施。
如果要测试浮点异常 (SIGFPE),func会指向采用可选的第二个参数的函数,此参数是在FLOAT.H中定义的采用FPE_xxx形式的几个清单常量之一。 当SIGFPE信号发生时,可以测试第二个参数的值以确定浮点异常的类型,然后采取相应措施。 此参数及其可能的值是 Microsoft 扩展名。
对于浮点异常,在接收到信号时不会重置func的值。 若要从浮点异常恢复,请使用 try/except 子句包围浮点运算。 将 setjmp 与 longjmp 一起使用也能恢复。 在任一情况下,调用进程都会继续执行,并保留未定义的进程的浮点状态。
如果信号处理程序返回,调用进程将在收到断点信号后立即继续执行,不考虑信号或操作模式的类型。
在执行指定的函数前,func 的值将设置为 SIG_DFL。 下一个中断信号将按照为 SIG_DFL 描述的方法处理,除非对 signal 的干预调用另行指定。 您可以使用此功能在所调用的函数中重置信号。
由于信号处理程序例程通常在中断发生时异步调用,当运行时操作不完整且处于未知状态时,信号处理程序可能受到控制。 以下列表汇总了一些限制,用来确定您可在信号处理程序例程中使用的函数。
不要发出低级别或
STDIO.HI/O 例程(例如,printf或fread)。不要调用堆例程或任何使用堆例程的例程(例如,
malloc、_strdup或_putenv)。 有关详细信息,请参阅malloc。不要使用生成系统调用的任何函数(例如,
_getcwd或time)。不要使用
longjmp,除非中断是由浮点异常导致的(即,sig是SIGFPE)。 在这种情况下,首先应使用对_fpreset的调用重新初始化浮点程序包。不要使用任何重叠例程。
如果某个程序要使用函数捕获SIGFPE异常,该程序必须包含浮点代码。 如果程序没有浮点代码并且需要运行库的信号处理代码,只需声明一个可变双精度值并将其初始化为零:
volatile double d = 0.0f;
SIGILL和SIGTERM信号不会在 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 函数