TTY abstraktion

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 30 augusti 2019; kontroller kräver 8 redigeringar .

TTY-undersystemet , eller TTY-abstraktion , är en av grunderna för Unix- eller Unix-liknande operativsystem, i synnerhet Linux . Detta system är avsett för användning av en terminal genom flera processer, vissa inmatningsmöjligheter (till exempel sändning av signaler med specialtangenter, radering av inmatade tecken).

Funktioner som att ändra färg på tecken och bakgrund, ändra stil på tecken, flytta markören beror på emuleringsprogrammet eller terminaldrivrutinen. Vanligtvis används ANSI escape-sekvenser för att implementera dem .

Historik

1869 uppfanns tickermaskinen  - en speciell telegrafmaskin för att överföra värdepapperskurser . Gradvis utvecklades denna enhet till teleskrivmaskinen  , en snabbare enhet baserad på ASCII -teckentabellen . En gång i tiden var teletyper från hela världen till och med kopplade till ett enda nätverk kallat Telex , där adressering utfördes enligt samma princip om en roterande axel med sökare som i dåtidens mekaniska automatiska telefonväxlar . Telexnätverket användes för att överföra kommersiella telegram. Men teletyper var ännu inte anslutna till datorer vid den tiden .

På 1960-talet kunde datorer utföra multitasking samtidigt . I synnerhet har realtidsinteraktion mellan en dator och en användare blivit möjlig . När den äldre batch-jobbbearbetningsmodellen ersattes av kommandoradsgränssnittet började teletyper användas som in- och utenheter , eftersom de redan fanns tillgängliga på marknaden.

Eftersom det fanns många olika modeller av teletyper, krävdes en viss nivå av mjukvarukompatibilitet för att abstrahera bort från en viss modell av teletyp. I UNIX- och UNIX-liknande system lämnades lågnivådriften av teletypen - till exempel antalet bitar per paket, baudhastighet , flödeskontroll , paritet , specialkoder för rudimentär sidformatering, etc. - till driften systemkärnan . Funktioner som markörrörelse , färgad text, etc., blev möjliga först i slutet av 1970 -talet , med tillkomsten av videoterminaler som VT-100 . Alla dessa avancerade funktioner lämnades till applikationerna .

Med den fortsatta utvecklingen av datorer blev teletyper och sedan videoterminaler ett minne blott. Men undersystemen för att arbeta med dem, även om de har genomgått betydande förändringar, förblev i operativsystemens kärnor.

Använd fall

Låt oss säga att användaren skriver på en teleskrivmaskin och att svaret skrivs ut av datorn. Teletypen används som en fysisk (riktig) terminal . Den ansluts till en dator med en universell seriell asynkron port . Operativsystemet har en portdrivrutin som ansvarar för den fysiska överföringen av bytes (paritet, flödeskontroll, etc.). I det enklaste fallet kan den här drivrutinen helt enkelt skicka data till applikationen som använder den. Följande funktioner kommer dock inte att vara tillgängliga:

Radredigering

Det innebär möjligheten att radera utskrivna tecken. Enligt UNIX-filosofin ska program hållas så enkla som möjligt , så denna funktion tillhandahålls av kärndrivrutinen, inte av teletypprogrammet. Operativsystemet tillhandahåller en buffert för redigering av text, samt några enkla redigeringskommandon - "radera tecken", "radera ord", "radera rad". Alla dessa funktioner är implementerade i linjedisciplinmodulen . De är aktiverade som standard ; detta läge kallas canonical, eller cooked (kokt). Programmet kan, om så önskas, inaktivera dessa funktioner genom att växla drivrutinen till råläge (rå). (De flesta interaktiva konsolprogram – textredigerare , e- postagenter , skal och alla program som använder Curses eller Readline – körs i råläge och hanterar alla redigeringskommandon själva.) Det nämnda protokolllagret låter dig också konfigurera eko (visning av inskrivna tecken på samma terminal), automatisk konvertering av radslut- och vagnreturtecken etc. Protokolllagret är alltså en primitiv texttolkare som Sed , och arbetar i kärnläge .

Poängen med att separera bearbetningen som beskrivs ovan i ett separat lager är att disciplinen (det vill säga den specifika drivkraften för detta lager) kan ändras dynamiskt . Till exempel, istället för en terminaldisciplin, kan du aktivera den paketkopplade datakommunikationsdisciplinen  - ppp , IrDA , seriell mus , etc.

Sessionshantering

Som regel vill användaren köra flera program samtidigt och interagera med dem i tur och ordning. Om programmet fryser , kommer användaren förmodligen att vilja kraschahenne. Processer som körs i bakgrunden bör blockeras så snart de vill visa lite text på skärmen. På samma sätt bör text som skrivits av användaren endast överföras till det för närvarande aktiva programmet. Operativsystemet implementerar alla dessa funktioner med hjälp av TTY-drivrutinen.

Både disciplinlagret (protokoll) och TTY-drivrutinen är passiva . De kan med andra ord inte vidta några åtgärder själva, utan är bara en uppsättning procedurer som kan anropas av andra procedurer. Däremot är själva operativsystemet en process , det vill säga det har sitt eget sammanhang .

Ett system med en UART-portdrivrutin, en disciplin (protokoll) och en TTY-drivrutin kallas en TTY-enhet , eller helt enkelt TTY . En användarprocess kan ändra beteendet hos vilken TTY-enhet som helst genom att manipulera dess motsvarande fili /dev- mappen . För detta måste naturligtvis denna process ha skrivbehörighet.till denna fil. Så när användaren loggar inoch ansluter till en specifik TTY, måste den användaren bli ägare till filen som motsvarar den TTY. Det är precis vad inloggningsprogrammet gör . (Själva inloggningsprogrammet körs som superanvändare ).

Tänk nu på fallet när systemet körs på en vanlig modern persondator . Disciplin och TTY-drivrutinen fungerar på samma sätt som tidigare, men UART-portdrivrutinen finns inte längre, eftersom det inte finns någon teletyp som skulle ansluta genom den. Istället används en videoterminalemulator  - ett program som imiterar en videoterminal (liknande en teleskrivmaskin, men med en videoskärm istället för ett pappersband), och visar innehållet i denna terminal på skärmen. Samtidigt körs detta program, till skillnad från konsolen , redan i användarutrymmet, snarare än kärnan, vilket ger mycket mer flexibilitet; till exempel kan du visa en terminal i ett fönster , som Xterm gör .

Pseudoterminal

För att tillåta driften av en terminalemulator i användarutrymmet, och samtidigt inte överge hela det ovan beskrivna TTY-undersystemet, uppfanns den så kallade pseudoterminalen, eller PTY. En pseudoterminal kan köras inuti en annan pseudoterminal; detta är vad Screen eller Ssh- klienten gör, till exempel .

En grafisk terminalemulator, som till exempel xterm , skapar först en ny pseudoterminal och en underordnad process som blir ledare för den nya sessionen, gör pseudoterminalens slav till sin styrterminal och startar en kommandotolk (de flesta ofta bash eller sh). Masterdelen av pseudoterminalen används av terminalemulatorn för att visa data som tas emot från slavdelen. Alla processer som startas från tolken, inklusive tolken själv, gör input ( stdin ) och output ( stdout och stderr ) genom slaven.

Det finns två API :er tillgängliga på Linux för att skapa en pseudoterminal ( pty(7)): UNIX 98 ( pts(4)) och BSD. [ett]

Det första alternativet är att öppna en fil /dev/ptmx(rekommenderas att använda int posix_openpt(int flags)), som kommer att binda den returnerade filbeskrivningen till värden och /dev/pts/skapa en ny slavfil i katalogen med ett positivt heltalsnamn. Varje öppning av denna fil skapar en ny pseudoterminal. För att ta reda på den exakta vägen till den drivna delen finns en funktion char* ptsname(int fd). Innan du öppnar den drivna delen måste du ringa grantptoch unlockpt.

När det gäller BSD /dev/finns det många filer av formen ttyXY(följare) och ptyXY(ledare) i katalogen.

Plats för TTY i processmodellen

I det här exemplet, med hjälp av kommandot ps l, kan du se statusen för varje process, och WCHAN-kolumnen visar händelsen som en viss sovprocess väntar på.

$ ps l F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIDKOMMANDAND 0 500 5942 5928 15 0 12916 1460 vänta Ss pts/14 0:00 -/bin/bash 0 500 12235 5942 15 0 21004 3572 vänta S+ pts/14 0:01 vim index.php 0 500 12580 12235 15 0 8080 1440 vänta S+ pts/14 0:00 /bin/bash -c (ps l) >/tmp/v727757/1 2>&1 0 500 12581 12580 15 0 4412 824 - R+ pts/14 0:00 ps l

STAT-kolumnen i utgången av ps-kommandot visar status för processen, men den kan också innehålla flera flaggor:

Det är dessa attribut som används för jobbkontroll . TTY-drivrutinens uppgift är att hålla reda på det aktiva processgrupps-ID (som explicit uppdateras av sessionens huvudprocess).

TTY och signalering

Följande signaler är direkt relaterade till TTY:

SIGHUP UART-portdrivrutinen skickar en sessionsomfattande SIGHUP-signal när modemet går in i luren på. Detta dödar vanligtvis alla processer i sessionen. Vissa program, som Screen eller Nohup , separeras från sin session och sin TTY så att deras underordnade processer inte dör när modemet kopplas bort. SIGINT SIGINT-signalen genereras av TTY-drivrutinen när ett specialtecken ^C(ASCII-koden för detta tecken är 3) visas i ingångsströmmen. Föraren skickar denna signal till det aktiva jobbet. Ett program som har tillgång till TTY kan ändra koden för detta specialtecken, eller inaktivera genereringen av denna signal helt och hållet. Sessionshanteraren håller reda på TTY-inställningarna som ställts in av var och en av de pågående uppgifterna och tillämpar dem när dessa uppgifter växlar. SIGQUIT I likhet med SIGINT, specialtecken att generera: ^\. SIGPIPE Denna signal är användbar i jobb eftersom den tillåter typkonstruktionen yes | headatt avsluta ja-processen när huvudprocessen avslutas. SIGCHLD Kärnan skickar en SIGCHLD-signal till en process när en av dess underordnade processer dör eller ändrar tillstånd. Tillsammans med SIGCHLD-signalen kan waitpiddu använda för att få ytterligare information, såsom processen och användar-ID:n, returkoden (eller signalen som orsakade kraschen). Med hjälp av denna signal övervakar sessionens värdprocess utförandet av sina uppgifter. SIGSTOPPA Denna signal avbryter exekveringen av processen som tar emot den. Endast init- processen kan bearbeta den . Vanligtvis använder inte kärnan denna signal. Istället ^Zskickar specialtecknet en SIGTSTP-signal, som redan kan fångas av applikationen; som regel utför applikationen vissa åtgärder, varefter den pausar sig själv - redan med en SIGSTOP-signal. SIGCONT Denna signal väcker den tidigare förlagda processen. Det skickas av skalet när användaren utfärdar ett kommando fg. Eftersom denna signal inte kan hanteras indikerar en oväntad SIGCONT-signal att processen avbröts och sedan väcktes. SIGTSTP SIGTSTP liknar SIGINT och SIGQUIT. Specialtecken ^Z( ASCII -kod 26). SIGTTIN När en process som körs i bakgrunden försöker läsa från en TTY, skickar TTY denna signal till hela jobbet. Detta avbryter vanligtvis jobbet tills användaren byter till det och kan ange förväntad data. SIGTTOU Liknar den föregående, men anropas när en bakgrundsprocess försöker skriva till en TTY. Denna signal från denna TTY kan inaktiveras. SIGWINCH TTY skickar en SIGWINCH-signal till det aktiva jobbet när terminalstorleken ändras.

Exempel

Betrakta följande exempel. Låt användaren redigera texten i en konsoltextredigerare. Markören är ungefär i mitten av skärmen, och redigeraren är bara upptagen med att utföra en uppgift som kräver mycket CPU-tid (till exempel söka och ersätta ord i en stor fil). Vid denna tidpunkt trycker användaren på ^Z.

Om disciplinen (länkprotokoll) konfigurerades för att fånga upp detta tecken, skulle användaren inte behöva vänta på att redigeraren ska slutföra det aktuella jobbet, eftersom disciplinskiktet omedelbart skulle skicka en SIGTSTP-signal till den aktiva uppgiften (dvs. den aktiva processen) grupp). Dessutom inkluderar denna grupp inte bara redaktören själv, utan också alla dess underordnade processer.

Låt redaktören ställa in manuell hantering av SIGTSTP-signalen. Kärnan anropar sedan avbrottshanteraren (inuti textredigeringsprocessen). Denna hanterare flyttar markören till den sista raden på skärmen genom att skriva en specifik sekvens av kontrolltecken till TTY. Eftersom editorn är en aktiv process, överförs och bearbetas dessa tecken omedelbart. Redaktören skickar sedan till sig själv (och dess processgrupp) en SIGSTOP-signal och går i viloläge.

Det faktum att textredigeraren har gått i viloläge signaleras till masterprocessen för sessionen med SIGCHLD-signalen (tillsammans med ID:n för sovprocesserna). När alla processer för den aktiva uppgiften går i viloläge kommer sessionsledaren ihåg de aktuella TTY-inställningarna och förklarar sig själv som den aktiva uppgiften för den TTY:en med syscallen ioctl. Den skriver sedan ut ett meddelande till användaren på skärmen om att den aktuella uppgiften har avbrutits.

Om kommandot anropas nu pskommer det att visa att textredigeraren är pausad (bokstaven "T"). Om du försöker väcka den - till exempel med ett inbyggt skal-kommando bgeller genom killatt skicka en SIGCONT-signal - kör editorn SIGCONT-signalhanteraren. Denna hanterare kommer att försöka rita om gränssnittet genom att skriva en sekvens av kontrolltecken till TTY. Men nu är redigeraren en bakgrundsprocess, så istället för att rendera gränssnittet kommer TTY att skicka en SIGTTOU-signal till redigeraren, och han kommer att somna om. Värdprocessen för sessionen kommer att veta om detta med SIGCHLD-signalen och kommer återigen att visa ett meddelande till användaren.

Om kommandot anropas istället kommer fgskalet att återställa de tidigare sparade TTY-inställningarna, göra editorn till den aktiva uppgiften igen och skicka den (och dess processgrupp) en SIGCONT-signal. Efter det kommer redigeraren att kunna rita sitt gränssnitt normalt, och arbetet kommer att fortsätta.

TTY-inställning

Du kan ta reda på TTY som hanterar ett givet skalprogram med hjälp av verktyget tty.

En öppen TTY kan konfigureras med ioctl. Det här gränssnittet är dock inte bärbart , så det rekommenderas att använda POSIX-kompatibla omslag istället (se man 3 termios).

TTY kan också konfigureras direkt från konsolen med hjälp av ett verktyg sttysom är baserat på API termios :et som nämns ovan :

$ stty -a hastighet 38400 baud; rader 73; kolumner 238; linje=0; intr = ^C; avsluta = ^\; radera = ^?; döda = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch=<undef>; start = ^Q; stopp = ^S; susp = ^Z; rprnt = ^R; wereas = ^W; nästa = ^V; spola = ^O; min = 1; tid = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel -iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

stty -avisar alla TTY-inställningar. En specifik TTY kan väljas med flaggan -F.

speedvisar hastigheten för UART-porten. Pseudoterminaler ignorerar detta värde.

rowsoch columnsvisa storleken på terminalen med tecken. I själva verket är dessa bara två numeriska variabler inuti TTY-drivrutinen som fritt kan läsas och modifieras. När de ändras kommer en SIGWINCH-signal att skickas till den aktiva uppgiften.

linevisar numret på den aktiva disciplinen. Alla discipliner som finns tillgängliga i systemet är listade i /proc/tty/ldiscs.

Specialtecknen listas härnäst, följt av de för närvarande valda alternativen. Ett streck betyder att alternativet är inaktiverat.

Exempel

Om du öppnar ett Xterm-fönster, kom ihåg dess TTY (genom att anropa kommandot tty) och storlek (genom att anropa kommandot stty -a), starta en helskärmskonsolapplikation (som vim ), och skriv sedan in ett annat Xterm-fönster stty -F X rows Y, där X är TTY namnet på det första fönstret, och Y är hälften av dess höjd , då kommer vim omedelbart att ta emot en SIGWINCH-signal i det första fönstret och rita om dess gränssnitt med endast hälften av fönstret som tillhandahålls till det.

Om du skriver i Xterm-fönstret stty intr okommer nu SIGINT-signalen att genereras när du skriver tecknet "o". I det här fallet kommer tryckning ^Cinte att leda till någonting.

Ibland fungerar inte backstegsknappen på ett UNIX-system . Detta beror på att terminalemulatorn skickar en annan ASCII-kod till TTY:n än den som är tilldelad funktionen i den TTY:n erase. För att lösa det här problemet måste du skriva stty erase ^Heller stty erase ^?. Det första kommandot ställer raderingstecknet till ASCII-kod 8, det andra till 127. Applikationer som körs i råläge påverkas inte av dessa inställningar.

Om du skriver i ett Xterm-fönster stty -icanoninaktiveras kanoniskt läge. Om du efter det försöker, till exempel, köra cat- programmet , kommer inte alla kortkommandon som ansvarar för textredigering, såsom ^Ueller till och med backsteg, att fungera. Dessutom kommer catden att ta emot (och följaktligen utdata) inte i rader, som tidigare, utan i separata tecken.

Om du skriver i ett Xterm-fönster stty -echokommer detta att inaktivera visningen av data du skriver. Att anropa programmet efter detta kommer att catvisa att data som skrivits på tangentbordet inte längre visas på skärmen (det vill säga du måste skriva texten "blindt"). Men efter att ha tryckt på Enter-tangenten skickar kärnan den senast utskrivna raden till programmet cat, och den kommer redan att visa den på skärmen.

Om du skriver i ett Xterm-fönster stty -tostopkan processer som körs i bakgrunden skriva till skärmen istället för att blockeras. Till exempel kommer kommandot (sleep 5; echo hello, world) &att visa en skalprompt, men efter 5 sekunder kommer raden att visas i konsolen «hello, world». Om du vid det här tillfället arbetar med terminalen (till exempel skriver lite text), så kommer den här raden att kilas in direkt i denna maskinskrivna text. Om du skriver stty tostopkommer kommandot (sleep 5; echo hello, world) &att blockera denna process med en SIGTTOU-signal, eftersom den efter 5 sekunder kommer att försöka visa text i bakgrunden. Vanligtvis visar skalet i sådana fall ett varningsmeddelande (antingen omedelbart eller vid nästa prompt).

Kommandot stty saneåterställer TTY-inställningarna till "sane" parametrar.

Mer information finns i systemet (info libc, "Jobbkontroll"). info

Anteckningar

  1. man 7 pty (15 september 2017). Hämtad 6 oktober 2017. Arkiverad från originalet 7 oktober 2017.

Källa