我有这个任务要做:
编写一个函数void myfunct(void(*f)(int sig))
,将其设置f
为所有可能信号的处理程序。
我有两个问题:
f
考虑到它需要一个参数,将函数设置为处理程序真的会起作用吗?不是应该没有任何参数吗?谢谢。
我个人会迭代信号编号的静态列表,并使用预处理器指令来检测支持哪些信号(在编译时)。例如:
#include <signal.h>
static const all_signals[] = {
#ifdef SIGHUP
SIGHUP, /* POSIX.1 */
#endif
#ifdef SIGQUIT
SIGQUIT, /* POSIX.1 */
#endif
#ifdef SIGTRAP
SIGTRAP, /* POSIX.1 */
#endif
#ifdef SIGIO
SIGIO, /* BSD/Linux */
#endif
/*
* Other signal names omitted for brevity
*/
/* C89/C99/C11 standard signals: */
SIGABRT,
SIGFPE,
SIGILL,
SIGINT,
SIGSEGV,
/* SIGTERM (C89/C99/C11) is also the terminating signal number */
SIGTERM
};
Run Code Online (Sandbox Code Playgroud)
是SIGTERM
安装信号处理程序的数组中的最后一个条目:
struct sigaction act;
int i = 0;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = your_signal_handler;
act.sa_flags = 0;
do {
if (sigaction(all_signals[i], &act, NULL)) {
fprintf(stderr, "Cannot install signal %d handler: %s.\n", all_signals[i], strerror(errno));
exit(EXIT_FAILURE);
}
} while (all_signals[i++] != SIGTERM);
Run Code Online (Sandbox Code Playgroud)
这样,您的代码不需要 POSIX 等支持即可工作,但如果在编译时可用,则支持 POSIX 信号。
您可以查看 Wikipedia Unix signal文章和man 7 signal来了解已知的信号名称。
您还可以使用以下命令安装 POSIX 实时信号的信号处理程序
#if SIGRTMAX-0 > SIGRTMIN-0
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
if (sigaction(i, &act, NULL)) {
fprintf(stderr, "Cannot install realtime signal %d handler: %s.\n", i, strerror(errno));
exit(EXIT_FAILURE);
}
#endif
Run Code Online (Sandbox Code Playgroud)
- 如何获得所有可能的信号?有这个功能吗?我可以以某种方式迭代它们吗?
大多数实现都提供一个常量,例如NSIG
(Glibc 提供NSIG
)或_NSIG
(Linux 提供 _NSIG)。因此,您可以循环该常量并为所有常量设置相同的信号处理函数。
POSIX 没有定义“最高信号编号”的值。POSIX 中有一项建议添加宏NSIG_MAX
。
{NSIG_MAX}
sysconf(_SC_NSIG) 的最大可能返回值。请参阅[XSH sysconf() 的交叉引用]。{NSIG_MAX} 的值不应大于 sigset_t 类型(参见 [交叉引用])能够表示的信号数量,忽略 sigfillset() 或 sigaddset() 施加的任何限制。
但它还没有进入 POSIX(很可能它会成为 POSIX 版本的一部分 - 第 8 期)。
- 考虑到它需要一个参数,将函数 f 设置为处理程序真的会起作用吗?不是应该没有任何参数吗?
当您设置信号配置时,信号处理函数采用的参数并不重要。它需要信号号,但这并不妨碍您将其用作多个信号的处理程序。
但有些特殊情况你需要处理。某些无法捕获或忽略的信号(SIGKILL
和SIGSTOP
)。还有其他信号(SIGFPE
、SIGILL
和SIGSEGV
),虽然允许捕获,但信号处理程序无法返回到其调用者(即您需要从信号处理程序退出)。