Emulatori terminali
Il lato master sostituisce la linea (la coppia di fili TX / RX) che va al terminale.
Il terminale visualizza i caratteri che riceve su uno dei fili (alcuni di questi sono caratteri di controllo e lo fanno fare cose come spostare il cursore, cambiare colore ...) e invia su un altro filo i caratteri corrispondenti ai tasti digitati.
Gli emulatori di terminale come xterm non sono diversi, tranne che invece di inviare e ricevere caratteri sui fili, leggono e scrivono caratteri sul loro descrittore di file sul lato principale. Una volta generato il terminale slave e avviato la shell, non lo toccano più. Oltre ad emulare la coppia di fili, xterm può anche modificare alcune delle proprietà della disciplina di linea tramite quel descrittore di file sul lato principale. Ad esempio, possono aggiornare gli attributi di dimensione in modo che un SIGWINCH venga inviato alle applicazioni che interagiscono con lo slave pty per notificare loro una dimensione modificata.
Oltre a ciò, c'è poca intelligenza nell'emulatore terminale / terminale.
Ciò che scrivi su un dispositivo terminale (come lo slave pty) è ciò che intendi essere visualizzato lì, ciò che leggi da esso è ciò che hai digitato lì, quindi non ha senso per l'emulatore di terminale leggere o scrivere su quello . Sono quelli all'altro capo.
La disciplina della linea tty
Molta intelligenza è nella disciplina della tty line . La disciplina di linea è un modulo software (residente nel driver, nel kernel) inserito sopra un dispositivo seriale / pty che si trova tra quel dispositivo e la linea / filo (il lato master per un pty).
Una linea seriale può avere un terminale all'altra estremità, ma anche un mouse o un altro computer per la rete. Ad esempio, è possibile collegare una disciplina della linea SLIP per ottenere un'interfaccia di rete sopra un dispositivo seriale (o dispositivo pty) oppure è possibile avere una disciplina della linea tty . La disciplina della linea tty è la disciplina della linea predefinita almeno su Linux per dispositivi seriali e pty. Su Linux, puoi cambiare la disciplina della linea con ldattach
.
Puoi vedere l'effetto della disabilitazione della disciplina tty line emettendo stty raw -echo
(nota che il prompt bash o altre applicazioni interattive come vi
impostare il terminale nella modalità esatta di cui hanno bisogno, quindi vuoi usare un'applicazione stupida come cat
sperimentare con quello). Quindi, tutto ciò che è scritto sul dispositivo terminale slave arriva immediatamente al lato master per la lettura di xterm e ogni carattere scritto da xterm sul lato master è immediatamente disponibile per la lettura dal dispositivo slave.
La disciplina di linea è quella in cui è implementato l' editor di linea interno del dispositivo terminale . Per esempio con stty icanon echo
(come di default), quando si digita a
, xterm scrive a
al maestro, poi la linea disciplina echi esso indietro (fa una a
disposizione per la lettura da parte xterm
per la visualizzazione), ma non fa nulla a disposizione per la lettura sul lato slave . Quindi se si digita backspace, xterm invia un carattere ^?
o ^H
, la disciplina di linea (come quella ^?
o ^H
corrisponde erase
all'impostazione della disciplina di linea) restituisce sul master a ^H
, space
e ^H
per xterm
cancellare ila
hai appena digitato sul suo schermo e ancora non invia nulla alla lettura dell'applicazione dal lato slave, aggiorna semplicemente il buffer dell'editor di linea interno per rimuovere quello a
che hai digitato in precedenza.
Quindi quando premi Invio, xterm invia ^M
(CR), che la disciplina di linea converte in input in un ^ J (LF), e invia ciò che hai inserito finora per leggere sul lato slave (un'applicazione che legge su /dev/pts/x
riceverà ciò che hai digitato incluso l'LF, ma non a
da quando l'hai eliminato), mentre sul lato principale invia un CR e un LF per spostare il cursore sulla riga successiva e l'inizio dello schermo.
La disciplina di linea è anche responsabile dell'invio del SIGINT
segnale al gruppo di processo in primo piano del terminale quando riceve un ^C
carattere sul lato master, ecc.
Molte applicazioni di terminale interattivo disabilitano la maggior parte delle funzionalità di quella disciplina di linea per implementarle da sole. Ma in ogni caso, attenzione al fatto che il terminale ( xterm
) è poco coinvolto in questo (tranne che per mostrare ciò che viene detto di mostrare).
E può esserci solo una sessione per processo e per dispositivo terminale. Una sessione può avere un terminale di controllo collegato ma non è necessario (tutte le sessioni iniziano senza un terminale fino a quando non ne aprono uno). xterm
, nel processo in cui si esegue l'esecuzione della shell in genere crea una nuova sessione (e quindi si stacca dal terminale da cui è stato avviato, xterm
se presente), apre la nuova /dev/pts/x
che ha generato, collegando quel dispositivo terminale alla nuova sessione. Quindi eseguirà la shell in quel processo, quindi la shell diventerà il leader della sessione. La shell o qualsiasi shell interattiva in quella sessione in genere si destreggeranno con gruppi di processi e tcsetpgrp()
, per impostare i lavori in primo piano e in background per quel terminale.
Per quanto riguarda quali informazioni sono memorizzate da un dispositivo terminale con una disciplina tty (seriale o pty) , questo è in genere ciò che il stty
comando visualizza e modifica. Tutta la configurazione della disciplina: dimensioni dello schermo del terminale, locale, flag di output, impostazioni per caratteri speciali (come ^ C, ^ Z ...), velocità di input e output (non rilevante per i pty). Ciò corrisponde alle funzioni tcgetattr()
/ tcsetattr()
che su Linux eseguono il mapping a TCGETS
/ TCSETS
ioctls e TIOCGWINSZ
/ TIOCSWINSZ
per le dimensioni dello schermo. Si può sostenere che l'attuale gruppo di processi in primo piano è un'altra informazione memorizzata nel dispositivo terminale ( tcsetpgrp()
/ tcgetpgrp()
, TIOC{G,S}PGRP
ioctls) o nel buffer di input o output corrente.
Si noti che le informazioni sulla dimensione dello schermo memorizzate nel dispositivo terminale potrebbero non riflettere la realtà. L'emulatore di terminale in genere lo imposterà (tramite lo stesso ioctl sulla dimensione principale) quando viene ridimensionata la sua finestra, ma può non essere sincronizzato se un'applicazione chiama lo ioctl sul lato slave o quando il ridimensionamento non viene trasmesso (nel caso di una connessione ssh che implica un altro pty generato da sshd
if ssh
ignora SIGWINCH
ad esempio). Alcuni terminali possono anche essere interrogati sulla loro dimensione tramite sequenze di escape, quindi un'applicazione può interrogarlo in quel modo e aggiornare la disciplina di linea con tali informazioni.
Per maggiori dettagli, ad esempio, puoi dare un'occhiata alle pagine man termios
e tty_ioctl
su Debian.
Per giocare con altre discipline di linea:
Emula un mouse con uno pseudo-terminale:
socat pty,link=mouse fifo:fifo
sudo inputattach -msc mouse # sets the MOUSE line discipline and specifies protocol
xinput list # see the new mouse there
exec 3<> fifo
printf '\207\12\0' >&3 # moves the cursor 10 pixels to the right
Sopra, il lato principale del pty è terminato da socat su una named pipe ( fifo
). Colleghiamo quel fifo a un processo (la shell) che scrive 0x87 0x0a 0x00 che nel protocollo del sistema del mouse significa no button pressed, delta(x,y) = (10,0)
. Qui, noi (la shell) non stiamo emulando un terminale, ma un mouse, i 3 byte che inviamo non devono essere letti (potenzialmente trasformati) da un'applicazione dal dispositivo terminale ( mouse
sopra la quale è un collegamento simbolico creato da socat
un /dev/pts/x
dispositivo) , ma devono essere interpretati come un evento di input del mouse.
Creare un'interfaccia SLIP:
# on hostA
socat tcp-listen:12345,reuseaddr pty,link=interface
# after connection from hostB:
sudo ldattach SLIP interface
ifconfig -a # see the new interface there
sudo ifconfig sl0 192.168.123.1/24
# on hostB
socat -v -x pty,link=interface tcp:hostA:12345
sudo ldattach SLIP interface
sudo ifconfig sl0 192.168.123.2/24
ping 192.168.123.1 # see the packets on socat output
Sopra, il filo seriale è emulato da socat
un socket TCP tra hostA e hostB. La disciplina della linea SLIP interpreta quei byte scambiati su quella linea virtuale come pacchetti IP incapsulati SLIP per la consegna sl0
sull'interfaccia.