在下面的程序中,如果我取消注释 _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_RESTART
,sigaction()
它将提供 BSD 语义,这正是您想要的。
关于c - XOPEN_SOURCE 和信号处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10715103/