yas*_*sar 8 c linux standards signals
在下面的程序中,如果我取消注释_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;
}
Run Code Online (Sandbox Code Playgroud)
问题是,signal()在安装信号处理函数时,该函数可以有两种不同形式的行为:
SIG_DFL——并且被信号中断的系统调用不会重新启动;或者在使用 glibc 的 Linux 上,如果已定义,您将获得 BSD 语义_BSD_SOURCE;如果未定义,您将获得 System V 语义。该_BSD_SOURCE宏是默认定义的,但如果您定义_XOPEN_SOURCE(或其他一些宏,例如_POSIX_SOURCE和_SVID_SOURCE),则此默认定义将被抑制。
在 System V 语义下,如果read()底层系统调用getchar()被中断,SIGINT那么getchar()将返回EOF并errno设置为EINTR(这将导致您的程序正常退出)。此外,在第一个信号之后,SIGINT该信号的处理将重置为默认值,并且默认操作是SIGINT终止进程(因此,即使您的程序在第一个信号中幸存下来SIGINT,第二个信号也会导致它异常退出)。
解决方案是根本不使用signal()安装信号处理函数;相反,您应该使用sigaction(),它是可移植的 - 它在任何地方都给出相同的语义。设置sa_flags为SA_RESTART,sigaction()它将给出 BSD 语义,这就是您想要的。