Come posso catturare sequenze di tasti singole in un'app console unix senza bloccare?

StackOverflow https://stackoverflow.com/questions/184108

  •  06-07-2019
  •  | 
  •  

Domanda

Ho un server TCP molto semplice scritto in C. Funziona indefinitamente, in attesa di connessioni. Su Windows, utilizzo select per verificare l'attività sul socket, e se non ce n'è uno, ho il seguente codice per consentirmi di uscire premendo 'q' sulla tastiera:

if( kbhit() ) {
   char c = getch();
   if( c == 'q' ) break;
}

Questo non funziona su unix, poiché kbhit non esiste e getch funziona in modo diverso. Ho trovato alcuni codice di esempio che utilizza tcsetattr per modificare le impostazioni del terminale e consentire l'inserimento carattere per carattere. Dopo aver chiamato la funzione init, apro / dev / stdin (con O_NONBLOCK ) e leggo un carattere, ma read (f, & amp; c, 1) si blocca fino a quando un carattere è colpito.

Suppongo di poter generare un thread separato e di farlo attendere indefinitamente e quindi segnalare il primo thread se l'utente preme 'q', ma sembra un po 'pesante. Sicuramente c'è un modo più semplice?

È stato utile?

Soluzione

Aggiungi stdin al tuo elenco di handle selezionati e, se contiene dati, chiama read per leggere un carattere da esso.

Altri suggerimenti

Piuttosto, aggiungi " f " dal tuo

read( f, &c, 1 )

per selezionare la chiamata. Quando f è pronto per la lettura, è stato premuto un carattere e read () non si bloccherà.

In Unix, sia sulla console di sistema che in una finestra del terminale X, l'I / O della tastiera passa attraverso un terminale virtuale. Device / dev / tty è il solito modo, in questi giorni, di accedere al terminale di controllo di un processo. Manipolazioni del dispositivo diverse da open / close / read / write sono tutte gestite dalla chiamata di sistema ioctl (2) per quel dispositivo specifico. L'idea generale di ciò che vuoi fare è

Apri il terminale di controllo (che può essere o meno stdin)

Cambia la modalità operativa su quel terminale per tornare senza aspettare una linea piena di input (che è il normale default)

Continua con il resto del programma, sapendo che le letture da quel terminale (che potrebbe essere stdin) possono restituire righe parziali o addirittura zero caratteri senza che si tratti di un errore o di una condizione di terminazione.


Una risposta dettagliata su come eseguire il secondo passaggio è disponibile nella Domande frequenti sulla programmazione in C . Sottolineano inoltre che si tratta di una domanda del sistema operativo, non di una lingua. Forniscono nove possibilità, ma le tre principali pertinenti a questa domanda sono

  1. Usa la libreria curses (3)
  2. Vecchi sistemi in stile BSD, utilizzare sgttyb per impostare CBREAK o RAW
  3. Posix o vecchi sistemi in stile System V, utilizzare TCGETAW / TCSETAW per impostare c_cc [VMIN] su 1 e c_cc [VTIME] su 0.

Seguire un paio di riferimenti nelle FAQ C potrebbe portare a questa pagina di frammenti di codice di kbhit .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top