替换 SIGUSR1 信号处理程序在标准 C11 和 GNU11 中的工作方式不同
Replacing the SIGUSR1 signal handler works differently in standards C11 and GNU11
我想覆盖 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 行为?
signal()
的行为根据某些功能测试宏定义在 System V 和 BSD 语义之间发生变化(请参阅该手册页上的可移植性)。
这种情况下的主要区别是 System V signal()
在调用时自动重置处理程序,而 BSD 不会。
使用 sigaction()
您可以设置您期望的行为(不设置 SA_RESETHAND
标志,可能设置 SA_RESTART
标志)。
如 signal()
联机帮助页所述:
The behavior of signal() varies across UNIX versions, and has also
varied historically across different versions of Linux. Avoid its
use: use sigaction(2) instead.
将 -D_DEFAULT_SOURCE
传递给 gcc
。如果您没有启用严格的标准一致性(即没有 -std=c*
选项),则此标志是隐式定义的。
这会将所有与 C 库相关的内容从 gnu11 获取到 c11。但是,它不会获得任何语法内容,例如 typeof
或其他。
我想覆盖 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 行为?
signal()
的行为根据某些功能测试宏定义在 System V 和 BSD 语义之间发生变化(请参阅该手册页上的可移植性)。
这种情况下的主要区别是 System V signal()
在调用时自动重置处理程序,而 BSD 不会。
使用 sigaction()
您可以设置您期望的行为(不设置 SA_RESETHAND
标志,可能设置 SA_RESTART
标志)。
如 signal()
联机帮助页所述:
The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead.
将 -D_DEFAULT_SOURCE
传递给 gcc
。如果您没有启用严格的标准一致性(即没有 -std=c*
选项),则此标志是隐式定义的。
这会将所有与 C 库相关的内容从 gnu11 获取到 c11。但是,它不会获得任何语法内容,例如 typeof
或其他。