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_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_IGN
SIGNAL.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.H
I/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
函数