Ingresso terminale canonico e non canonico

Sto studiando per un esame e sono confuso su come funziona l’input / output canonico e non canonico in Unix (es. Curses). Capisco che c’è un buffer a cui vengono applicate le “discipline di linea” per l’input canonico. Questo significa che il buffer è bypassato per input non canonico, o significa semplicemente che non vengono applicate le discipline di linea? In che modo questo processo differisce per le operazioni di input e output?

Nei programmi curses con cui ho lavorato dimostra l’input canonico, l’input digitato da un utente viene inserito automaticamente sia dopo che un certo numero di caratteri sia stato digitato che dopo un certo periodo di tempo. L’una o l’altra cosa sono considerate “discipline di linea” o è qualcosa di completamente diverso?

Per l’input canonico – pensa shell; in realtà, pensa alla buona vecchia shell Bourne, dal momento che Bash e i suoi parenti hanno un editing da riga di comando. Digiti una riga di input; se si commette un errore, si utilizza il carattere di cancellazione (l’impostazione predefinita è Backspace , in genere, a volte Elimina ) per cancellare il carattere precedente. Se si incasina completamente, è ansible annullare l’intera riga con il carattere di interruzione di riga (non completamente standardizzato, spesso Control-X ). Su alcuni sistemi, ottieni una parola cancellata con Control-W . Tutto questo è un input canonico. L’intera riga viene raccolta e modificata fino al carattere di fine riga – Return – viene premuto. Quindi, l’intera linea è resa disponibile per i programmi in attesa. A seconda delle chiamate di sistema read() che sono in sospeso, l’intera riga sarà disponibile per essere letta (da una o più chiamate a read() ).

Per l’input non canonico – si pensi a vi o vim o altro – si preme un carattere, ed è immediatamente disponibile per il programma. Non sei trattenuto finché non tocchi il tuo ritorno. Il sistema non modifica i caratteri; sono resi disponibili al programma non appena vengono digitati. Spetta al programma interpretare le cose in modo appropriato. Ora, vim fa un certo numero di cose che assomigliano un po ‘a un input canonico. Ad esempio, backspace si sposta all’indietro e in modalità input cancella cosa c’era. Ma questo perché vim sceglie di farlo comportarsi in quel modo.

L’output canonico e non canonico è un’attività molto meno seria. Ci sono alcuni bit e pezzi di differenza, legati a cose come se echo carriage-return prima di line-feed, e se fare ritardi (non necessario con l’elettronica, importante nei giorni in cui il dispositivo di output potrebbe essere un 110- baud teletype). Può anche fare cose come gestire dispositivi di output senza distinzione tra maiuscole e minuscole – teletipi, di nuovo. Le lettere minuscole vengono visualizzate in maiuscole e le lettere maiuscole come backslash e maiuscole.

In passato, digitando tutte le lettere maiuscole nel prompt di accesso, il programma di accesso veniva automaticamente convertito nella modalità in cui tutte le maiuscole venivano visualizzate con una barra rovesciata davanti a ciascun capitale effettivo. Sospetto che non sia più fatto su terminali elettronici.


In un commento, TitaniumDecoy ha chiesto:

Quindi con l’input non canonico, il buffer di input è completamente ignorato? Inoltre, da dove vengono le discipline di linea?

Con l’input non canonico, il buffer di input è ancora utilizzato; se non vi è alcun programma con una chiamata read() attesa di input dal terminale, i caratteri vengono mantenuti nel buffer di input. Quello che non succede è una modifica del buffer di input.

Le discipline di linea sono cose come l’insieme di manipolazioni eseguite dall’editing. Quindi, un aspetto della disciplina di linea è che il carattere di cancellazione cancella un carattere precedente nella modalità di input canonico. Se hai icase (input case-mapping), i caratteri maiuscoli vengono mappati in minuscolo se non preceduti da una barra rovesciata; questa è una disciplina di linea, credo, o un aspetto di una disciplina di linea.


Ho dimenticato di menzionare che l’elaborazione EOF ( Control-D ) è gestita in modalità canonica; in realtà significa ‘rendere l’input accumulato disponibile per read() ‘; se non vi è alcun input accumulato (se si digita Control-D all’inizio di una riga), quindi read() restituirà zero byte, che viene quindi interpretato come EOF dai programmi. Naturalmente, puoi digitare allegramente più caratteri sulla tastiera, e i programmi che ignorano EOF (o eseguiti in modalità non canonica) saranno abbastanza felici.

Ovviamente, in modalità canonica, i caratteri digitati sulla tastiera vengono normalmente riportati sullo schermo; puoi controllare se si verifica tale eco. Tuttavia, questo è un po ‘tangenziale per l’input canonico; la normale modifica avviene anche quando l’eco è distriggersto.

Allo stesso modo, i segnali di interruzione e uscita sono artefatti dell’elaborazione in modalità canonica. Così pure i segnali di controllo del lavoro come Control-Z per sospendere il processo corrente e tornare alla shell. Allo stesso modo, il controllo del stream ( Control-S , Control-Q per arrestare e avviare l’uscita) viene fornito in modalità canonica.

Capitolo 4 della Advanced Unix Programming di Rochkind , 2nd Edn copre l’I / O del terminale e fornisce molte di queste informazioni – e molto altro ancora. Anche altri libri di programmazione UNIX (almeno quelli buoni) lo copriranno.