




Краткий ответ: изучите функцию signal, в частности, улавливание SIGINT. Вы пишете функцию обратного вызова и передаете ее системе через функцию сигнала, а затем, когда происходит этот конкретный сигнал, система вызывает вашу функцию обратного вызова. Вы можете закрыть файлы и сделать там все, что захотите.
Вы должны поймать СИГНАЛ. Что-то вроде этого:
void sigint_handler(int sig)
{
[do some cleanup]
signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
}
загружает более подробную информацию здесь
Намного лучше использовать sigaction ().
Джонатан, пожалуйста, расширите это утверждение.
ответ выше расширяет его (stackoverflow.com/questions/368927/…)
Для полноценного рабочего примера вы можете попробовать следующий код:
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
volatile bool STOP = false;
void sigint_handler(int sig);
int main() {
signal(SIGINT, sigint_handler);
while(true) {
if (STOP) {
break;
}
}
return 0;
}
void sigint_handler(int sig) {
printf("\nCTRL-C detected\n");
STOP = true;
}
Пример выполнения:
[user@host]$ ./a.out
^C
CTRL-C detected
STOP следует объявить изменчивым, иначе компилятор может произвести некоторую (некорректную) оптимизацию.
Я не специалист по C++, поэтому верю вам на слово и обновлю образец кода :-)
Технически это тоже должен быть sig_atomic_t. POSIX позволяет вам делать больше в обработчике сигналов, чем ISO C. Также вам следует использовать sigaction (). Помимо прочего, если пользователь использует программу для быстрой генерации двух прерываний, ваша программа может умереть с использованием signal () вместо sigaction ().
Обратите внимание на людей, которые могут наткнуться на этот вопрос, вместо этого ища ответ в Окна:
Используйте вызов API SetConsoleCtrlHandler, чтобы установить собственный обработчик и следить за CTRL_C_EVENT, CTRL_BREAK_EVENT или CTRL_CLOSE_EVENT.
signal() может быть опасен в некоторых операционных системах и не рекомендуется в Linux в пользу sigaction(). "сигнал против подписи"
Вот пример, с которым я недавно столкнулся ("Коснитесь сигнала прерывания") и который изменил, когда играл с ним.
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
struct sigaction old_action;
void sigint_handler(int sig_no)
{
printf("CTRL-C pressed\n");
sigaction(SIGINT, &old_action, NULL);
kill(0, SIGINT);
}
int main()
{
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = &sigint_handler;
sigaction(SIGINT, &action, &old_action);
pause();
return 0;
}
Действия в sigint_handler () после printf () нечетные - почему? Кроме того, вы должны pause () вместо цикла while. Инициализация для нового действия тоже не идеальна. Это, вероятно, работает, но это немного рассеянный подход «будем надеяться, что все нули в порядке».
Я обновил его, чтобы использовать pause () вместо цикла while, так как это действительно имеет больше смысла даже для демонстрационного кода. Как я уже сказал в посте, код изначально был взят из другого источника. Возможно, я неправильно его прочитал, но я подумал, что это сэкономит и восстановит любые существующие обработчики сигналов.
Это хороший рабочий пример, но я думаю, что struct sigaction action, old_action; должно быть действием struct sigaction; То есть, похоже, вы переопределили имя своего глобального old_action в main ().
Обратите внимание, что sigaction не является частью ISO 9899 (стандарт C), тогда как signal входит в его состав. Для переносимости вместо этого может быть полезно использовать signal, особенно когда различия в реализации некритичны (например, обработчик сигнала, завершающий программу).
Намного лучше использовать sigaction ().