本篇 ShengYu 介紹 C/C++ 捕捉 ctrl+c 事件的 2 種方法,第 1 種是 signal 方式,第 2 種是 sigaction 方式,
signal 方式
這個方式適用於大多數系統,這是標準 C 函式庫就有支援,我們這邊要捕捉的是 ctrl+c 的事件,對應的是 SIGINT signal,
所以我們需要的是使用 signal()
函式註冊 SIGINT 這個事件發生時,要來執行我們預先定義好的 signal_handler 函式,
注意這邊的 sig_handler 是有註冊成功的 signal 才會進來,例如我這邊只有註冊 SIGINT,所以 SIGINT 這個 signal 會進來 sig_handler,其他的像 SIGABRT、SIGSEGV、SIGILL、SIGTERM 等等沒註冊的自然不會進 sig_handler,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// g++ cpp-signal-sigint.cpp -o a.out -std=c++11
void signal_handler(int signum) {
printf("signal_handler: caught signal %d\n", signum);
if (signum == SIGINT) {
printf("SIGINT\n");
exit(1);
}
}
int main() {
if (signal(SIGINT, signal_handler) == SIG_ERR) {
printf("Failed to caught signal\n");
}
while(1) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
輸出如下,按下 Ctrl+C 後會看到 ^C
字樣,接著就進入到我們定義的 signal_handler 函式裡,然後判斷是 SIGINT 就離開程式,1
2^Csignal_handler: caught signal 2
SIGINT
sigaction 方式
這邊我們示範另外一種 sigaction 的方式,比上述的 signal 還強大,能處理更複雜的功能,不過我們這邊只是要用來攔住 ctrl+c 的事件而已,用法如下,
事先需要先初始化好 sigaction 結構的變數,再用 sigaction()
來註冊 SIGINT 的事件,這個事件發生時就會來執行我們預先定義好的 signal_handler 函式,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// g++ cpp-sigaction-sigint.cpp -o a.out -std=c++11
void signal_handler(int signum) {
printf("signal_handler: caught signal %d\n", signum);
if (signum == SIGINT) {
printf("SIGINT\n");
exit(1);
}
}
int main() {
struct sigaction sa;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) == -1) {
printf("Failed to caught signal\n");
}
while(1) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
效果是跟前一個方法一樣。
其它參考
c++ - How can I catch a ctrl+c event? - Stack Overflow
https://stackoverflow.com/questions/1641182/how-can-i-catch-a-ctrl+c-event