GNU/Linux >> Linux Esercitazione >  >> Linux

Perché Linux emette sempre ^C premendo Ctrl+C?

È il terminale (driver) che intercetta il ^C e lo traduce in un segnale inviato al processo collegato (che è la shell) stty intr ^B indicherebbe invece al driver del terminale di intercettare un ^B. È anche il driver del terminale che rimanda ^C al terminale.

La shell è solo un processo che si trova dall'altra parte della linea e riceve il suo stdin dal tuo terminale tramite il driver del terminale (come /dev/ttyX), e anche il suo stdout (e stderr) sono collegati allo stesso tty .

Si noti che (se l'eco è abilitato) il terminale invia le sequenze di tasti a entrambi il processo (gruppo) e ritorno al terminale. Il comando stty è solo un wrapper attorno a ioctl() per il driver tty per i processi che "controllano" tty.

AGGIORNAMENTO:per dimostrare che la shell non è coinvolta, ho creato il seguente programmino. Dovrebbe essere eseguito dalla sua shell madre tramite exec ./a.out (sembra che una shell interattiva eseguirà comunque il fork di una shell figlia) Il programma imposta la chiave che genera SIGINTR su ^B, disattiva l'eco e quindi attende l'input da 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.

La shell fa eco a tutto ciò che digiti, quindi quando digiti ^C , anche questo viene echeggiato (e nel tuo caso intercettato dal tuo gestore di segnale). Il comando stty -echo può o non può esserti utile a seconda delle tue esigenze/vincoli, vedi la pagina man di stty per maggiori informazioni.

Ovviamente molto di più accade a un livello inferiore, in qualsiasi momento comunichi con un sistema tramite i driver dei dispositivi periferici (come il driver della tastiera che usi per generare il segnale ^C e il driver del terminale che visualizza tutto) sono coinvolti. Puoi scavare ancora più a fondo a livello di linguaggio assembly/macchina, registri, tabelle di ricerca, ecc. Se desideri un livello di comprensione più dettagliato e approfondito, i libri seguenti sono un buon punto di partenza:

Il design del sistema operativo Unix è un buon riferimento per questo genere di cose. Altri due riferimenti classici:Unix Programming Environment e Advanced Programming in the UNIX Environment

Bel riassunto qui in questa domanda SO In che modo Ctrl-C termina un processo figlio?

"quando esegui un programma, ad esempio find , la shell:

  • lo stesso fork della shell
  • e per il bambino imposta la gestione del segnale predefinita
  • sostituisci il figlio con il comando dato (ad es. con find)
  • quando premi CTRL-C, la shell genitore gestisce questo segnale ma il figlio lo riceverà - con l'azione predefinita - termina. (anche il bambino può implementare la gestione del segnale)"

Linux
  1. Perché la sostituzione del comando Shell divora un carattere di nuova riga finale?

  2. Come convertire l'output della shell di Linux in HTML?

  3. Come eseguo l'output di testo colorato su un terminale Linux?

  4. Perché pr_debug del kernel Linux non fornisce alcun output?

  5. Perché Bash è ovunque (nella maggior parte se non in tutte le distribuzioni Linux)?

5 modi per dividere il tuo terminale Linux

Perché amo ancora Alpine per la posta elettronica sul terminale Linux

Lolcat:uno strumento da riga di comando per generare Rainbow Of Colors nel terminale Linux

Come rendere natalizio il tuo terminale e shell Linux

Bash Scripting:come generare e formattare il testo su Linux Shell

Come posso nascondere l'output di un'applicazione shell in Linux?