在C中捕获Ctrl-C
如何在C中捕获Ctrl + C?
用信号处理程序。
下面是一个简单的例子,翻转main()
使用的bool
:
#include <signal.h> static volatile int keepRunning = 1; void intHandler(int dummy) { keepRunning = 0; } // ... int main(void) { signal(SIGINT, intHandler); while (keepRunning) { // ...
编辑在2017年6月 :为什么它可能涉及,尤其是那些有永不知足的编辑这个答案的冲动。 看,我七年前写了这个答案。 是的,语言标准改变了。 如果你真的必须改善世界,请添加你的新答案,但离开我的。 因为答案上有我的名字,所以我更愿意包含我的话。 谢谢。
在这里检查:
注意:显然,这是一个简单的例子,解释了如何设置一个Ctrl C处理程序,但是一如既往,有些规则需要遵守,以免破坏别的东西。 请阅读下面的评论。
上面的示例代码:
#include <stdio.h> #include <signal.h> #include <stdlib.h> void INThandler(int); int main(void) { signal(SIGINT, INThandler); while (1) pause(); return 0; } void INThandler(int sig) { char c; signal(sig, SIG_IGN); printf("OUCH, did you hit Ctrl-C?\n" "Do you really want to quit? [y/n] "); c = getchar(); if (c == 'y' || c == 'Y') exit(0); else signal(SIGINT, INThandler); getchar(); // Get new line character }
有关UN * X平台的增编。
根据GNU / Linux上的signal(2)
手册页, signal
的行为不如sigaction
行为便携:
signal()的行为在UNIX版本中有所不同,并且在不同版本的Linux中历史上也有所不同。 避免使用:改用sigaction(2)。
在系统V上,系统没有阻塞信号的进一步实例的传送,并且传送信号会将处理程序重置为默认值。 在BSD中,语义改变了。
Dirk Eddelbuettel先前回答的以下变化使用sigaction
而不是signal
:
#include <signal.h> #include <stdlib.h> static bool keepRunning = true; void intHandler(int) { keepRunning = false; } int main(int argc, char *argv[]) { struct sigaction act; act.sa_handler = intHandler; sigaction(SIGINT, &act, NULL); while (keepRunning) { // main loop } }
设置一个陷阱(可以用一个处理程序捕获多个信号):
信号(SIGQUIT,my_handler); 信号(SIGINT,my_handler);
处理信号,但是你要知道的限制和陷阱:
void my_handler(int sig) { / *你的代码在这里。 * / }
或者你可以把terminal设置为原始模式,如下所示:
struct termios term; term.c_iflag |= IGNBRK; term.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF); term.c_lflag &= ~(ICANON | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN); term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSANOW, &term);
现在应该可以使用fgetc(stdin)
来读取Ctrl + C的按键。 小心使用这个,因为你不能像正常一样Ctrl + Z , Ctrl + Q , Ctrl + S等等。
关于现有的答案,请注意信号处理是依赖于平台的。 例如,Win32处理的信号比POSIX操作系统less得多; 看到这里 。 尽pipe在Win32的signals.h中声明了SIGINT,但请参阅文档中的说明,说明它不会达到您所期望的效果。
这只是退出之前打印。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void sigint_handler(int); int main(void) { signal(SIGINT, sigint_handler); while (1){ pause(); } return 0; } void sigint_handler(int sig) { /*do something*/ printf("killing process %d\n",getpid()); exit(0); }
#include<stdio.h> #include<signal.h> #include<unistd.h> void sig_handler(int signo) { if (signo == SIGINT) printf("received SIGINT\n"); } int main(void) { if (signal(SIGINT, sig_handler) == SIG_ERR) printf("\ncan't catch SIGINT\n"); // A long long wait so that we can easily issue a signal to this process while(1) sleep(1); return 0; }
函数sig_handler检查传递的参数的值是否等于SIGINT,然后执行printf。