Linux中Ctrl + C中断事件处理

37

我正在开发一个应用程序,使用C++语言编写,并使用Linux GNU C编译器进行编译。

我想在用户使用 Ctrl + C 快捷键中断脚本的同时调用一个函数。

我该怎么做?非常感谢任何答案。


你需要为SIGINT定义信号处理程序,可以从这段代码中获取灵感:http://stackoverflow.com/questions/17705842/is-there-a-way-to-make-my-program-work-with-less-code - Grijesh Chauhan
10
这与所使用的编译器有什么关系呢?请问。 - user529758
3
“GCC认可的库”这个说法并不存在。如果有一个用标准C语言编写的库,任何正常的C编译器都应该能够进行编译。 - user529758
Grijesh,你能给我举个例子吗?我只需要定义一个kill事件,但我没有任何想法。 - mozcelikors
1
可能是在C语言编写的Linux TCP/IP服务器中处理Ctrl-C的重复问题。 - user2485710
3个回答

76
当你按下 Ctr + C 时,操作系统会向进程发送一个信号。有许多信号,其中之一是SIGINT。 SIGINT(“程序中断”)是终止信号之一。
还有几种终止信号,但关于SIGINT的有趣之处在于它可以被程序处理(捕获)。 SIGINT的默认操作是程序终止。也就是说,如果您的程序没有特别处理此信号,则按下Ctr + C时,您的程序将以默认操作终止。
要更改信号的默认操作,必须注册要捕获的信号。要在C程序中注册信号(至少在POSIX系统下),有两个函数
  1. signal(int signum, sighandler_t handler);
  2. sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);.
这些函数需要在您的C代码中包含头文件signal.h。下面是一个带有注释的signal函数的简单示例。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h> //  our new library 
volatile sig_atomic_t flag = 0;
void my_function(int sig){ // can be called asynchronously
  flag = 1; // set flag
}

int main(){
  // Register signals 
  signal(SIGINT, my_function); 
  //      ^          ^
  //  Which-Signal   |-- which user defined function registered
  while(1)  
    if(flag){ // my action when signal set it 1
        printf("\n Signal caught!\n");
        printf("\n default action it not termination!\n");
        flag = 0;
    }     
  return 0;
}  

注意:你应该只在信号处理器中调用安全 / 授权函数。例如,避免在信号处理器中调用printf
你可以使用gcc编译这段代码,并从shell中执行它。代码中有一个无限循环,它将一直运行,直到你通过按下Ctr + C发送SIGINT信号。

2
你可以留下评论来表达你的疑问,我会尽力给你一个快速的起点。我相信只要再付出一些努力,你就能深入了解这些事情。 - Grijesh Chauhan
我非常确定该进程被发送了一个信号,而不是单个。 :-) - celtschk
@Duck 嘿,Duck,谢谢你!我的英语非常差,我仔细注意了你的编辑,并知道了我的错误。我会改进的。谢谢! - Grijesh Chauhan
1
@ Grijesh Chauhan,欢迎你,但是你的英语并不差。我只是填补了一些漏洞。 - Duck

13

按下CtrlC通常会使Shell向您的程序发送SIGINT信号。通过signal(2)sigaction(2)添加处理程序,您可以在按下CtrlC时进行任何你想做的事情。

或者,如果您只关心在程序退出之前执行清理操作,则可以通过atexit(3)设置退出处理程序更为适当。


3
atexit()不是一种替代方案,因为以这种方式注册的函数在由信号导致的程序退出时不会被调用。 - Emanuel P

6
您可以使用信号宏。
以下是如何处理它的示例:
#include <signal.h>
#include <stdio.h>
void sigint(int a)
{
    printf("^C caught\n");
}
int main()
{
    signal(SIGINT, sigint);
    for (;;) {}
}

示例输出:

Ethans-MacBook-Pro:~ phyrrus9$ ./a.out
^C^C caught
^C^C caught
^C^C caught
^C^C caught
^C^C caught

11
避免在信号处理程序中使用printf。 - Grijesh Chauhan
就这么简单。我用它来关闭i2c连接,这样printf就会被替换为关闭连接的函数。非常感谢。 - mozcelikors

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接