在 C 中导致 gets() 在 SIGINT 上退出
Cause gets() to exit on SIGINT in C
我正在编写一个简单的 C 程序,它使用 gets() 函数一次从键盘(循环)读取一行文本。
如果用户按下 CTRL-C,循环必须立即退出。我知道如何编写一个 sig 处理程序,它可以设置一个标志来退出循环......但是我如何在这个信号到达时立即使 gets() 函数return?
您应该使用 select()
在从标准输入读取之前检查数据是否可用:
void handler (int arg) {
// handle signal
}
int main (void) {
char buf[100];
signal(SIGINT, handler);
do {
fd_set f;
FD_ZERO(&f);
FD_SET(fileno(stdin), &f);
int st = select(fileno(stdin)+1, &f, NULL, NULL, NULL);
if (st == 1) {
fgets(buf, sizeof(buf), stdin);
// Handle input
}
} while (st >= 0);
exit(EXIT_SUCCESS);
}
select()
将 return 与 -1
(errno EINTR) 在从信号处理程序 returning 之后,而 read()
(由 (f) 调用gets) 将自动恢复。
使用linux,还有另一种可能使用sigaction()
:
void handler (int arg) {
// handle signal
}
int main (void) {
char buf[100], *p;
struct sigaction sa = { .sa_handler = handler, .sa_flags = 0, .sa_mask = 0 };
sigaction(SIGINT, &sa, NULL);
do {
p = fgets(buf, sizeof(buf), stdin);
// handle input
} while (p);
printf("Byebye\n");
exit(EXIT_SUCCESS);
}
由于在 sa_flags
中没有为信号处理程序指定标志 SA_RESTART
,因此 slow 设备上的 read()
(即终端、管道、插座)也将 return 和 -1 (EINTR)
(另请参见 signal(7))。
虽然更简单一些,但不同 unix-flavors(甚至 kernel-versions)之间的行为可能会有所不同,因此第一个版本是更安全且更 portable/reliable 的方式。
我正在编写一个简单的 C 程序,它使用 gets() 函数一次从键盘(循环)读取一行文本。
如果用户按下 CTRL-C,循环必须立即退出。我知道如何编写一个 sig 处理程序,它可以设置一个标志来退出循环......但是我如何在这个信号到达时立即使 gets() 函数return?
您应该使用 select()
在从标准输入读取之前检查数据是否可用:
void handler (int arg) {
// handle signal
}
int main (void) {
char buf[100];
signal(SIGINT, handler);
do {
fd_set f;
FD_ZERO(&f);
FD_SET(fileno(stdin), &f);
int st = select(fileno(stdin)+1, &f, NULL, NULL, NULL);
if (st == 1) {
fgets(buf, sizeof(buf), stdin);
// Handle input
}
} while (st >= 0);
exit(EXIT_SUCCESS);
}
select()
将 return 与 -1
(errno EINTR) 在从信号处理程序 returning 之后,而 read()
(由 (f) 调用gets) 将自动恢复。
使用linux,还有另一种可能使用sigaction()
:
void handler (int arg) {
// handle signal
}
int main (void) {
char buf[100], *p;
struct sigaction sa = { .sa_handler = handler, .sa_flags = 0, .sa_mask = 0 };
sigaction(SIGINT, &sa, NULL);
do {
p = fgets(buf, sizeof(buf), stdin);
// handle input
} while (p);
printf("Byebye\n");
exit(EXIT_SUCCESS);
}
由于在 sa_flags
中没有为信号处理程序指定标志 SA_RESTART
,因此 slow 设备上的 read()
(即终端、管道、插座)也将 return 和 -1 (EINTR)
(另请参见 signal(7))。
虽然更简单一些,但不同 unix-flavors(甚至 kernel-versions)之间的行为可能会有所不同,因此第一个版本是更安全且更 portable/reliable 的方式。