在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 + ZCtrl + QCtrl + 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。