Я хочу создать определенную комбинацию клавиш клавиатуры для завершения процесса, например, я хочу завершить процесс нажатием CTRL + C ^ 3 (троекратное нажатие C: CTRL + CCC).
По сути, я хочу заменить CTRL + C на CTRL + CCC.
решение1
Поведение по умолчанию Ctrl+ Cпредставляет собой комбинацию двух вещей. Драйвер терминала¹ не передает это нажатие клавиши, а вместо этого отправляетСигнал SIGINTк процессу переднего плана². По умолчанию процесс завершается, когда он получает SIGINT, но процесс может установить обработчик сигнала, а затем он запустит обработчик сигнала, когда получит SIGINT.
Невозможно настроить драйвер терминала так, чтобы он преобразовывал только третий Ctrl+ Cв строке для завершения процесса переднего плана. Чтобы сделать это, вам нужно сосчитать до трех в вашей программе. Есть два способа сделать это, которые будут вести себя по-разному, если пользователь нажмет что-то еще между Ctrl+ C.
Один из способов — отключить поведение Ctrl+ Cпо отправке сигнала и сообщить драйверу терминала, что вместо этого нужно передать его. Это можно сделать, вызвавstty intr \^-
из скрипта оболочки илиtcsetattr(fd, &termios)
с termios.c_cc[VINTR]
установленным значением _POSIX_VDISABLE
из C. Затем в цикле обработки ввода вашей программы выйдите, когда увидите три символа Ctrl+ Cподряд.
Другой способ — установить обработчик сигнала для SIGINT, который подсчитывает, сколько раз он был вызван, и завершает программу на третий раз. Вы можете захотеть сбросить счетчик, если между ними есть нормальный ввод.
¹ Не эмулятор терминала, а общая часть операционной системы, которая обрабатывает все терминалы.
² Я только объясняю простой случай. Это не трактат о том, как работает драйвер терминала.
решение2
Вы не можете изменить привязку клавиш в своем коде, поскольку сигнал — это программное прерывание, которое ОС отправляет процессу. Когда пользователь нажимает ctrl-c, другой процесс что-то сообщает вашему процессу.
Есть фиксированный набор сигналов, которые могут быть отправлены процессу. Сигналы похожи на прерывания, разница в том, что прерывания опосредуются процессором и обрабатываются ядром, тогда как сигналы опосредуются ядром (возможно, через системные вызовы) и обрабатываются процессами. Ядро может передать прерывание как сигнал процессу, который его вызвал (типичные примеры — SIGSEGV, SIGBUS, SIGILL и SIGFPE).
Вы можете переназначить привязку клавиш сигнала на своем компьютере с помощью stty
Включите Ctrl+C для копирования и Ctrl+Shift+C для прерывания
https://docstore.mik.ua/orelly/unix3/upt/ch05_08.htm
если вы хотите ровно 3 нажатия ctrl-c, вы можете посчитать SIGINT и прервать программу при 3 нажатиях ctrl-c. (нажатие трех раз C: CTRL +CCC).
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signo)
{
static int counter=0;
if (signo == SIGINT)
counter++;
printf("received SIGINT %d times\n", counter);
if (counter == 3)
exit(0);
}
int main()
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
while(1)
sleep(1);
return 0;
}