我想覆盖SIGUSR1信号处理程序的行为。但是使用不同的C标准我得到了不同的结果。如果我使用 C11 标准,我的信号处理程序在收到此信号一次后会替换为默认信号。因此,如果我将信号SIGUSR1发送到进程两次,那么第二次,将调用默认的SIGUSR1处理程序而不是我的处理程序。但是在 GNU11 标准中,每次都调用我的。如何使用 C11 标准获得此行为?
这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
void noop(int signo)
{
(void) signo;
}
int main(int argc, char **argv)
{
(void) argc; (void) argv;
if (signal(SIGUSR1, noop) == SIG_ERR)
{
perror("Can't register handler for signal SIGUSR1");
exit(EXIT_FAILURE);
}
while (1);
}
使用 C11 标准编译此程序:
gcc signal.c -o signal_c11.out -std=c11 -O0 -Wall -Wextra -Wpedantic
./signal_c11.out
或者用 GNU11 标准编译这个程序:
gcc signal.c -o signal_gnu11.out -std=gnu11 -O0 -Wall -Wextra -Wpedantic
./signal_gnu11.out
在另一个终端中,执行
kill -s SIGUSR1 <pid-of-above-process>
kill -s SIGUSR1 <pid-of-above-process>
然后,来自程序 signal_c11.out 的进程将根据SIGUSR1信号的默认操作终止;但来自程序 signal_gnu11.out 的进程将继续运行,这是我所期望的。
如何使用 c11 标准获得 gnu11 行为?
基于某些功能测试宏定义在 System V 和 BSD 语义之间更改signal()
行为(请参阅该手册页上的可移植性(。
在这种情况下,主要区别在于 System Vsignal()
调用处理程序时自动重置处理程序,而 BSD 不会。
使用sigaction()
您可以设置预期的行为(不设置SA_RESETHAND
标志,可能设置SA_RESTART
标志(。
正如signal()
手册页所说:
signal(( 的行为因 UNIX 版本而异,并且还具有 历史上不同版本的 Linux 各不相同。 避免其 使用:改用 sigaction(2(。
将-D_DEFAULT_SOURCE
传递给gcc
。如果未启用严格的标准一致性(即没有-std=c*
选项(,则隐式定义此标志。
这将获得从 gnu11 到 c11 的所有与 C 库相关的内容。但是,它不会获得任何语法内容,例如typeof
或其他语法。