c - XOPEN_SOURCE 和信号处理

标签 c linux signals standards

在下面的程序中,如果我取消注释 _XOPEN_SOURCE 行,当我点击 C-c 时我的程序终止,如果我不注释该行,相同的程序不会终止.任何人都知道 _XOPEN_SOURCE 以何种方式影响信号处理?我在 Linux 上使用 gcc (4.6.3) 和 glibc (2.15)。

/* #define _XOPEN_SOURCE 700 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

typedef void (*sighandler_t)(int);

void handle_signal(int signo)
{
    printf("\n[MY_SHELL] ");
    fflush(stdout);
}

int main()
{
    int c;
    signal(SIGINT, SIG_IGN);
    signal(SIGINT, handle_signal);
    printf("[MY_SHELL] ");
    while ((c = getchar()) != EOF) {
        if (c == '\n')
            printf("[MY_SHELL] ");
    }
    printf("\n");
    return 0;
}

最佳答案

问题是 signal() 函数在安装信号处理函数时可以有两种不同形式的行为:

  • System V 语义,其中信号处理程序是“一次性”的 - 也就是说,在调用信号处理函数后,信号的处置被重置为 SIG_DFL - 并且系统调用被中断通过信号不重新启动;或
  • BSD 语义,其中信号处理程序在信号触发时重置,信号在信号处理程序执行时被阻止,并且大多数中断的系统调用会自动重新启动。

在带有 glibc 的 Linux 上,如果定义了 _BSD_SOURCE,您将获得 BSD 语义,如果未定义,则获得 System V 语义。 _BSD_SOURCE 宏是默认定义的,但如果您定义了 _XOPEN_SOURCE(或其他一些宏,如 _POSIX_SOURCE_SVID_SOURCE)。

在 System V 语义下,如果底层 getchar()read() 系统调用被 SIGINT 中断,则 getchar( ) 将返回 EOF 并将 errno 设置为 EINTR(这将导致您的程序正常退出)。此外,在第一个 SIGINT 之后,该信号的处理被重置为默认值,并且 SIGINT 的默认操作是终止进程(因此即使您的程序幸存下来第一个 SIGINT,第二个会导致它异常退出)。

解决方案是完全不使用 signal() 来安装信号处理函数;相反,您应该使用可移植的 sigaction() - 它在任何地方都提供相同的语义。 sa_flags 设置为 SA_RESTARTsigaction() 它将提供 BSD 语义,这正是您想要的。

关于c - XOPEN_SOURCE 和信号处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10715103/

相关文章:

c - 如何处理标准输入错误状态?

c - Windows 上的 GCC : Set "Description" field of C executable?

regex - 处理彩色 bash 提示符

linux - Linux内核 'do_select'函数内部无限循环

C++/Qt - 从一个线程到另一个线程槽的信号

c - 如何使用递归技术检查值X是否是列表L的成员

c++ - 如何通过固定线程循环周期最小化 CPU 消耗

linux - 如何在 Vim 中的行首和行尾添加/*?

c - 将信号从 pthread 发送到 QObject

linux - 为什么信号没有被屏蔽?