Quali sono le responsabilità di ciascun componente Pseudo-Terminale (PTY) (software, lato master, lato slave)?


59

Sto cercando di capire come funziona un tty 1 (il flusso di lavoro e le responsabilità di ciascun elemento). Ho letto diversi articoli interessanti a riguardo, ma ci sono ancora alcune aree sfocate.

Questo è quello che ho capito finora:

  • Il terminale emulato effettua diverse chiamate di sistema verso /dev/ptmx, la parte principale dello pseudo-terminale.
  • La parte master dello pseudo terminale alloca un file /dev/pts/[0-N], corrispondente alla porta seriale obsoleta, e "allega" uno pseudo terminale slave ad esso.
  • Lo pseudo terminale slave conserva informazioni come ID sessione, lavoro in primo piano, dimensioni dello schermo.

Ecco le mie domande:

  1. Ptmx ha qualche scopo oltre a allocare la parte slave? Fornisce una sorta di "intelligenza" o il terminale emulato (ad esempio xterm) ha tutta l'intelligenza di comportarsi come un terminale?
  2. Perché xterm deve interagire con la parte master, poiché inoltra solo lo stdout e lo stdin della parte slave? Perché non può scrivere e leggere direttamente dal file pts ?
  3. Un ID di sessione è sempre allegato a un file pts e viceversa? Potrei digitare un comando ps e ho trovato 2 sessionId per lo stesso / dev / pts / X ?
  4. Quali altre informazioni ptsmemorizza? Xterm aggiorna tutti i campi da solo o ptmaggiunge "intelligenza" su di esso?

1. Baso la mia comprensione sul TTY demistificato da Linus Akesson e sui post del kernel Linux di Andries Brouwer , come su molte altre domande su questi siti

Risposte:


58

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 viimpostare il terminale nella modalità esatta di cui hanno bisogno, quindi vuoi usare un'applicazione stupida come catsperimentare 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 aal maestro, poi la linea disciplina echi esso indietro (fa una adisposizione per la lettura da parte xtermper 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 ^Hcorrisponde eraseall'impostazione della disciplina di linea) restituisce sul master a ^H, spacee ^Hper xtermcancellare ilahai 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 ache 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/xriceverà ciò che hai digitato incluso l'LF, ma non ada 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 SIGINTsegnale al gruppo di processo in primo piano del terminale quando riceve un ^Ccarattere 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, xtermse presente), apre la nuova /dev/pts/xche 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 sttycomando 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/ TCSETSioctls e TIOCGWINSZ/ TIOCSWINSZper 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}PGRPioctls) 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 sshdif sshignora SIGWINCHad 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 termiose tty_ioctlsu Debian.

Per giocare con altre discipline di linea:

  1. 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 ( mousesopra la quale è un collegamento simbolico creato da socatun /dev/pts/xdispositivo) , ma devono essere interpretati come un evento di input del mouse.

  2. 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 socatun 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 sl0sull'interfaccia.


1
Questa è la risposta migliore Lo segnalo come giusto e lo voto. Puoi aggiungere l'ultima parte sulle informazioni che negozi pts? Secondo questa pagina (capitolo che configura il dispositivo TTY) , i pt memorizzano valori come il numero di righe e il numero di righe. Sono altre informazioni che memorizza?
Pierre-Jean,

@ Pierre-Jean, aggiunte ulteriori informazioni.
Stéphane Chazelas,

Sebbene la tua risposta sia ben oltre soddisfacente, sarebbe interessante vedere un esempio più semplice su come si crea effettivamente un / dev / pts / M. Ho provato a usare cat /dev/ptmx &quale apre un nuovo pty, ma poi non c'è alcun processo che posso trovare associato ad esso, quindi come lo useresti? Secondo, ci ho provato echo "1" >/dev/ptmx, ma non ha fatto nulla ... Perché mi interessa questo? Perché spesso quando ci si connette in remoto tramite ssh(ad esempio), si ottiene PTY allocation request failedo No controlling tty: open /dev/ttyerrore, che impedisce il controllo del lavoro. Sarebbe bello capire meglio quelli.
not2qubit

@ user1147688, come creare un pty sarebbe una domanda diversa. Questa è già troppe domande alla volta. Ma vedi la tua ptypagina man per i dettagli.
Stéphane Chazelas,

@ StéphaneChazelas Piccoli chiarimenti: 1. Quindi stai dicendo che il flusso è come physical term---- tty---- bashsui terminali e pty(m)---- tty---- pty(s)---- bashsugli emulatori dei terminali? La ttydisciplina era responsabile dell'eco dei personaggi anche sul terminale fisico? 2. È il programma di emulazione terminale che si collega alla tastiera / schermo per gestire l'input? 3. Secondo quello che ho capito, hai detto che il buffering di linea dei comandi bash / tutti gli input dei terminali è fatto dalla ttydisciplina di linea invece che dai buffer I / O delle funzioni CI / O. È corretto?
Forumulator

29

Modifica: da questa risposta, ho scritto un articolo dedicato sul mio blog, per le persone che sarebbero interessate a maggiori dettagli.


Dopo molte letture, questo è quello che ho capito.

  • Ptmx ha qualche scopo oltre a allocare la parte slave? Fornisce una sorta di "intelligenza" o il terminale emulato (ad esempio xterm) ha tutta l'intelligenza di comportarsi come un terminale?

    /dev/ptmxnon alloca la parte slave : alloca la "parte master pseudo terminale". / dev / ptmx non è il pseudo terminale principale : è un multiplexer principale pseudo terminale . È stato creato con lo standard Unix98 PTY per evitare le condizioni di gara durante l'allocazione dello pseudo terminale principale ( sorgente ).

    La parte master (ptm) del pseudo terminale non è rappresentata nel file system. È rappresentato da un descrittore di file.

    La parte slave (pts) è rappresentata da un file in /dev/pts/Ncui Nè un numero.

    I punti si ottiene dal PTM attraverso la chiamata successiva grandpt, unlockpt, ptsname. ( Sorgente )

    Il ptm sostituisce il driver AUR dedicato alla comunicazione con il dispositivo e l'edizione linea. Quindi non emula in alcun modo un terminale ma fornisce la funzionalità di line edition e fornisce un modo per visualizzare e comunicare con i punti. ( Fonte )

    Ecco un grafico di ciò che era un TTY collegato a un dispositivo hardware Comunicazione TTY con AUR

    Ed ecco un grafico di un tty collegato a un ptm Comunicazione TTY con PTM

    Il file ptm gestisce diversi argomenti Ioctl (ISPTM, UNLKPT, TIOCREMOTE, TIOCSIGNAL) rispetto ai punti.

  • Perché xterm deve interagire con la parte master, poiché inoltra solo lo stdout e lo stdin della parte slave? Perché non può scrivere e leggere direttamente dal file pts?

    I processi interagiscono con i dispositivi tramite azioni eseguite su un file virtuale (lettura, scrittura, ioctl ..). Il file stesso non esiste e il driver utilizza il file per attivare azioni quando vengono chiamati metodi di lettura o scrittura. (Vedi allegato per informazioni sui conducenti)

    Un TTY definisce un modo preciso di interagire con esso. I processi scrivono e leggono dal dispositivo e si aspettano lo stesso comportamento indipendentemente dal tipo di TTY implementato.

    • la funzione di lettura viene utilizzata dai processi per leggere le voci dal terminale
    • La funzione di scrittura viene utilizzata dai processi per inviare l' output al terminale

    I pts si comportano come un driver TTY. Il suo metodo di lettura e scrittura viene utilizzato per implementare il comportamento del driver TTY. Poiché non esiste un dispositivo reale per inviare i dati, viene creata una coppia di stream e il ptm implementa una funzione di lettura per leggere i dati inviati da pts allo stream e una funzione di scrittura per inviare i dati allo stream che saranno disponibili quando i punti lo leggeranno.

    Ricorda, il file che rappresenta un dispositivo non è un file classico e xterm, se vuoi vedere cosa è stato scritto nel file, non può semplicemente chiamarlo aperto e leggerlo, poiché queste funzioni hanno un comportamento completamente diverso qui.

  • Un ID di sessione è sempre allegato a un file pts e viceversa? Potrei digitare un comando ps e ho trovato 2 sessionId per lo stesso / dev / pts / X?

    Non credo, l'Id della sessione è definito dal primo processo che allega i pts (bash in generale) e non vedo un modo per creare un'altra sessione e collegarlo agli stessi pts. Forse uno strumento del genere socatpotrebbe farlo?

  • Quali altre informazioni memorizza i pts? Xterm aggiorna tutti i campi da solo o il ptm aggiunge "intelligenza" su di esso?

    I pts memorizzano 2 categorie di informazioni riguardanti il ​​terminale con cui sta comunicando: il Terminfoe il Termcap. Di solito, molti emulatori di terminali si basano su librerie che gestiscono per loro informazioni sui termcap (che forniranno ad esempio tutti i valori di capacità per emulare un VTX100). Un esempio di tale libreria è la libvte . Modifica (vedi commento Stephane Chazelas): le capacità del terminale non sono memorizzate dai punti.

annesso


termcap e terminfo sono database sulle funzionalità dell'emulatore di terminale o terminale, non hanno nulla a che fare con i dispositivi tty o pty.
Stéphane Chazelas,

Ok, modificherò la mia risposta. Grazie per il commento. Puoi aggiungere queste informazioni sui pts alla tua risposta se lo conosci (a quanto pare pts memorizza le dimensioni dello schermo, per esempio)?
Pierre-Jean,

6
Queste sono belle immagini. Quale software hai usato per realizzarli?
Gilles 'SO- smetti di essere malvagio' il

5
@Gilles Grazie. Li ho fatti con Inkscape , un editor di grafica vettoriale open source. Forse non è il modo più efficiente per realizzare questo tipo di grafica, ma se sei interessato, ho scritto un articolo su come creare questo tipo di disegni isometrici.
Pierre-Jean,

Non credo che tu possa mai associare due sessioni a un terminale di controllo o lasciare che una sessione abbia più di un terminale di controllo
炸鱼 薯条 德里克

9

Ecco uno schema che ho fatto qualche tempo fa su come sshdfunziona. Non riguarda il funzionamento della disciplina di linea e roba del genere, ma aggiunge un'illustrazione della vita reale di chi interagisce con cosa:

inserisci qui la descrizione dell'immagine


Grazie mille per questo. Ho trascorso 2 giorni cercando di capirlo. Mi sto solo chiedendo cosa succede quando nessuna istanza è istanziata. stdin non esiste, va bene, ma dove sono scritti stdout e stderr?
Amico

@emmasculateur felice di averti aiutato. Spiacente, non riesco a capire cosa intendi con "quando non viene istanziata nessuna pty". Puoi fare un esempio di quando pty non è istanziato?
Boris Burkov,

1
Con "nessuna pty viene istanziata" intendo quando si esegue ssh con -T, che l'uomo dice che disabilita l'allocazione pseudo-terminale. es: ssh -T emasculateur@localhost "sleep 10" quindi ps aux|grep sleepmostra questo: emasculateur 21826 0.0 0.0 23032 3728 ? Ss 02:49 0:00 zsh -c sleep 10 In quel caso dove scrive bash stdoute stderr? Spero che la mia domanda abbia un senso.
Amico

@emmasculateur hm, è una buona domanda, ha senso, non ci avevo pensato prima. Immagino che sia così, inizi il tuo processo come demone su macchina remota, senza terminale associato. La mia ipotesi è che il suo input / output / errore standard vada proprio /dev/nullcome per un normale demone, ma non ne sono sicuro. Vedi anche: serverfault.com/questions/593399/…
Boris Burkov il

@emmasculateur Mi sono anche imbattuto in un caso diverso dal tuo: se il tuo processo aveva un terminale, ma quel terminale era chiuso, il processo avrebbe ricevuto SIGHUP dal kernel al tentativo di leggere / scrivere su stdout / stdin. Questo spesso uccide i lavori, avviati tramite ssh senza nohupo screen/ tmux.
Boris Burkov,

0

man pts dice:

Il file / dev / ptmx è un file di caratteri con il numero maggiore 5 e il numero minore 2, di solito in modalità 0666 e proprietario. Gruppo di root.root. Viene utilizzato per creare una coppia master e slave pseudo-terminale.

Quando un processo apre / dev / ptmx, ottiene un descrittore di file per un master pseudo-terminale (PTM) e un dispositivo pseudo-terminale slave (PTS) viene creato nella directory / dev / pts. Ogni descrittore di file ottenuto aprendo / dev / ptmx è un PTM indipendente con il proprio PTS associato, il cui percorso può essere trovato passando il descrittore a ptsname (3).

Prima di aprire lo slave pseudo-terminale, è necessario passare il descrittore di file del master a grantpt (3) e unlockpt (3).

Una volta aperti sia il master che lo slave pseudo-terminale, lo slave fornisce ai processi un'interfaccia identica a quella di un terminale reale.

I dati scritti sullo slave vengono presentati sul descrittore principale come input. I dati scritti sul master vengono presentati allo slave come input.

In pratica, gli pseudo-terminali vengono utilizzati per l'implementazione di emulatori di terminali come xterm (1), in cui i dati letti dal master pseudo-terminale vengono interpretati dall'applicazione nello stesso modo in cui un terminale reale interpreterebbe i dati e per l'implementazione remota programmi di accesso come sshd (8), in cui i dati letti dal master pseudo-terminale vengono inviati attraverso la rete a un programma client collegato a un terminale o un emulatore di terminale.

Gli pseudo-terminali possono anche essere usati per inviare input a programmi che normalmente rifiutano di leggere input da pipe (come su (8) e passwd (8)).

Circa /dev/pts/X indexing:

ogni X è una sessione che la apri, quindi gli schiavi devono indicizzarli.

A proposito TeteType (/dev/ttyN):

La sua vera console è stata generata dal tuo sistema di avvio come sysV.

Informazioni su Why slave insted of master: http://commons.wikimedia.org/wiki/File:Termios-script-diagram.png


Mi dispiace, ma non hai risposto alle domande. Ho già letto la pagina man e ho visto questo grafico, ma il comportamento non era chiaro. Puoi, come suggerisce IlluminÉ, estendere la tua risposta in base alle domande?
Pierre-Jean,

SORRY FOR LATE
Golfo Persico

Per utilizzare il sottosistema pseudo-TTY, è necessario installare un nodo per il driver lato master / dev / ptmx e il numero N di driver slave (N viene determinato al momento dell'installazione). I nomi dei dispositivi slave sono / dev / pts / M dove M ha i valori da 0 a N-1. Un utente accede a un dispositivo pseudo-TTY tramite il dispositivo principale (chiamato ptm) a sua volta accessibile tramite il driver clone. Il dispositivo principale è impostato come dispositivo clone in cui il suo numero di dispositivo principale è il maggiore per il dispositivo clone e il suo il numero di dispositivo minore è il maggiore per il driver ptm.
Golfo Persico,

si ho letto man pan page ....!
Golfo Persico

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.