替换SIGUSR1信号处理程序在标准C11和GNU11中的工作方式不同

问题描述 投票:2回答:2

我想重写SIGUSR1信号处理程序的行为。但是我使用不同的C标准会得到不同的结果。如果我使用C11标准,则一次收到此信号后,信号处理程序将替换为默认信号处理程序。因此,如果我两次将信号SIGUSR1发送到该进程,则第二次调用默认的SIGUSR1处理程序,而不是我的。但是在GNU11标准中,每次都会调用mine。如何使用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>

然后,根据SIGUSR1信号的默认操作,来自signal_c11.out程序的过程将终止;但信号Signal_gnu11.out中的进程将继续运行,与我期望的一样。

如何使用c11标准获得gnu11行为?

c signals standards c11
2个回答
3
投票

基于某些功能测试宏定义,signal()的行为在System V和BSD语义之间改变(请参见该手册页的可移植性。

在这种情况下的主要区别是,系统V signal()在调用处理程序时会自动重置处理程序,而BSD不会。

使用signal(),您可以设置期望的行为(不设置sigaction()标志,可能设置sigaction()标志。

正如SA_RESETHAND联机帮助说:

signal()的行为在UNIX版本中有所不同,并且还具有历史上在不同版本的Linux中有所不同。避免其用途:改为使用sigaction(2)。


1
投票

SA_RESTART传递到signal()。如果您未启用严格的标准符合性(即没有-D_DEFAULT_SOURCE选项),则会隐式定义此标志。

这将从gnu11到C11的所有C库相关内容。但是,它不会获得任何语法内容,例如gcc或其他。

© www.soinside.com 2019 - 2024. All rights reserved.