我试图使用sigaction来忽略ctrl。当我按下ctrl,^Cctrl而不是^C,它不会立即打印下一个提示符。只有在我点击输入之前,它才开始打印提示符。如下所示:
> // run the program sigAction
$./sigAction
sigAction>^Cctrl-C
// it is waiting,waiting . Nothing happens until I hit Enter, next prompt comes up.
sigAction>我正在寻找的结果是,当我点击ctrl而没有按回车时,下一个提示应该立即出现。问题如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <string.h>
5 // implement ignoring ctrl-C
6 void sigIntHandler(int signum) {
7 fprintf(stderr, "ctrl-C\n" );
8
9 }
10
11 main()
12 {
13
14 struct sigaction signalAction;
15 signalAction.sa_handler = sigIntHandler;
16 sigemptyset(&signalAction.sa_mask);
17 signalAction.sa_flags = SA_RESTART;
18 sigaction(SIGINT, &signalAction, NULL);
19 while(1) {
20
21 char block[4096];
22
23 printf("sigAction>");
24 fflush(stdout);
25
26 fgets(block, 4096, stdin);
27
28 if (!strcmp(block, "exit\n")) {
29 exit(1);
30 }
31 }
32 } 当我使用gdb查看内部时,它提供了以下信息:
(gdb) n
Single stepping until exit from function main,
which has no line number information.
sigAction>^C
Program received signal SIGINT, Interrupt.
0x00007ffff7b15d10 in __read_nocancel () from /lib64/libc.so.6
(gdb) n
Single stepping until exit from function __read_nocancel,
which has no line number information任何想法都有帮助!提前感谢!
发布于 2016-08-15 17:43:28
正如我在评论中指出的那样,您并不真正想使用SA_RESTART。这意味着当read()收到一个中断时,在中断后继续读取,这就排除了主程序打印新提示符的机会。
这段代码很可能接近您想要的内容:
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void sigIntHandler(int signum)
{
fprintf(stderr, "Ctrl-C (%d)\n", signum);
}
int main(void)
{
struct sigaction signalAction;
signalAction.sa_handler = sigIntHandler;
sigemptyset(&signalAction.sa_mask);
signalAction.sa_flags = 0; // SA_RESTART;
sigaction(SIGINT, &signalAction, NULL);
while (1)
{
char block[4096];
printf("sigAction>");
fflush(stdout);
if (fgets(block, 4096, stdin) == 0)
{
if (errno == EINTR)
{
errno = 0;
clearerr(stdin);
fprintf(stderr, "Interrupted!\n");
continue;
}
else
{
fprintf(stderr, "EOF spotted\n");
break;
}
}
if (!strcmp(block, "exit\n"))
{
fprintf(stderr, "Exiting\n");
exit(1);
}
printf("Read: [%.*s]\n", (int)(strlen(block) - 1), block);
}
}注意,在官方上,您不应该在信号处理程序中使用printf()系列函数--参见 in a signal handler?
示例运行(名为sigact的程序):
$ ./sigact
sigAction>Ordinary input
Read: [Ordinary input]
sigAction>Some typing, then an interrupt! ^CCtrl-C (2)
Interrupted!
sigAction>More input?
Read: [More input?]
sigAction>Yes, more input.
Read: [Yes, more input.]
sigAction>And why you type control-D?
Read: [And why you type control-D?]
sigAction>EOF spotted
$ ./sigact
sigAction>Also typing exit works, of course.
Read: [Also typing exit works, of course.]
sigAction>exit
Exiting
$^C来自终端驱动程序(在MacOSX10.11.6上)。echoctl在lflags的第一行末尾执行以下操作:
$ stty -a
speed 9600 baud; 50 rows; 141 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
-ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = <undef>; erase = ^?; intr = ^C; kill = ^X; lnext = ^V;
min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
stop = ^S; susp = ^Z; time = 0; werase = ^W;
$发布于 2016-08-15 17:36:46
如果您想忽略,那么使用SIG_IGN作为操作,如果不是,则不是忽略而是捕捉。
当您使用SA_RESTART时,中断的系统调用将是restard而不是中断。然后,fgets可能会在某些内部系统调用中被阻塞,然后指定重新启动它。我不记得fgets在被中断时的行为,但是它可能会返回一个NULL值。您还可以使用read和控制errno来实现EINTR。
https://stackoverflow.com/questions/38959797
复制相似问题