Je to terminál (ovladač), který zachytí ^C a převede jej na signál odeslaný připojenému procesu (což je shell) stty intr ^B
by dal pokyn ovladači terminálu, aby místo toho zachytil ^B. Je to také ovladač terminálu, který vrací ^C zpět do terminálu.
Shell je jen proces, který sedí na druhém konci linky a přijímá svůj stdin z vašeho terminálu přes ovladač terminálu (jako /dev/ttyX) a jeho stdout (a stderr) jsou také připojeny ke stejnému tty .
Všimněte si, že (pokud je povolena ozvěna) terminál odesílá stisknuté klávesy oběma proces (skupinu) a zpět na terminál. Příkaz stty je pouze obalem kolem ioctl()s pro ovladač tty pro procesy "řídící" tty.
AKTUALIZACE:Abych demonstroval, že shell není zapojen, vytvořil jsem následující malý program. Měl by být spuštěn jeho nadřazeným shellem přes exec ./a.out
(zdá se, že interaktivní shell rozvětví dceřiný shell, tak jako tak) Program nastaví klíč, který generuje SIGINTR, na ^B, vypne echo a poté čeká na vstup ze stdin.
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
int thesignum = 0;
void handler(int signum);
void handler(int signum)
{ thesignum = signum;}
#define THE_KEY 2 /* ^B */
int main(void)
{
int rc;
struct termios mytermios;
rc = tcgetattr(0 , &mytermios);
printf("tcgetattr=%d\n", rc );
mytermios.c_cc[VINTR] = THE_KEY; /* set intr to ^B */
mytermios.c_lflag &= ~ECHO ; /* Dont echo */
rc = tcsetattr(0 , TCSANOW, &mytermios);
printf("tcsetattr(intr,%d) =%d\n", THE_KEY, rc );
printf("Setting handler()\n" );
signal(SIGINT, handler);
printf("entering pause()\n... type something followed by ^%c\n", '@'+THE_KEY );
rc = pause();
printf("Rc=%d: %d(%s), signum=%d\n", rc, errno , strerror(errno), thesignum );
// mytermios.c_cc[VINTR] = 3; /* reset intr to ^C */
mytermios.c_lflag |= ECHO ; /* Do echo */
rc = tcsetattr(0 , TCSANOW, &mytermios);
printf("tcsetattr(intr,%d) =%d\n", THE_KEY, rc );
return 0;
}
intr.sh:
#!/bin/sh
echo $$
exec ./a.out
echo I am back.
Shell opakuje vše, co napíšete, tedy když napíšete ^C
, který se také odešle (a ve vašem případě zachytí váš obslužný program signálu). Příkaz stty -echo
může nebo nemusí být pro vás užitečné v závislosti na vašich potřebách/omezeních, další informace naleznete v manuálové stránce stty.
Mnohem více se samozřejmě děje na nižší úrovni, kdykoli komunikujete se systémem prostřednictvím ovladačů periferních zařízení (jako je ovladač klávesnice, který používáte ke generování signálu ^C, a ovladač terminálu, který vše zobrazuje). Můžete se ponořit ještě hlouběji na úrovni jazyka assembleru/stroje, registrů, vyhledávacích tabulek atd. Pokud chcete podrobnější a hlubší úroveň porozumění, je dobré začít níže uvedené knihy:
Návrh operačního systému Unix je dobrou referencí pro tyto druhy věcí. Další dva klasické odkazy:Unixové programovací prostředí a pokročilé programování v UNIXovém prostředí
Pěkné shrnutí zde v této otázce SO Jak Ctrl-C ukončí podřízený proces?
"když spustíte program, například find
, shell:
- samotnou vidlici shellu
- a pro dítě nastavit výchozí zpracování signálu
- nahraďte dítě daným příkazem (např. find)
- když stisknete CTRL-C, nadřazený shell tento signál zpracuje, ale podřízený jej přijme – s výchozí akcí – ukončí. (dítě může také implementovat zpracování signálu)"