
Unter Lubuntu 18.04 führe ich eine Shell in lxterminal aus. Das steuernde Terminal ist der aktuelle Pseudoterminal-Slave:
$ tty
/dev/pts/2
Ich möchte wissen, welche Beziehungen zwischen meinem aktuellen Steuerterminal /dev/pts/2
und bestehen /dev/tty
.
/dev/tty
verhält sich wie mein aktuelles Steuerterminal/dev/pts/2
:$ echo hello > /dev/tty hello $ cat < /dev/tty world world ^C
Es scheint sich jedoch um nicht miteinander verbundene Dateien zu handeln, statt dass die eine ein symbolischer oder fester Link zur anderen ist:
$ ls -lai /dev/tty /dev/pts/2 5 crw--w---- 1 t tty 136, 2 May 31 16:38 /dev/pts/2 13 crw-rw-rw- 1 root tty 5, 0 May 31 16:36 /dev/tty
Bei verschiedenen Sitzungen mit unterschiedlichen Steuerterminals
/dev/tty
ist garantiert, dass es sich um deren Steuerterminals handelt. Wie können es unterschiedliche Steuerterminals sein, ohne dass es sich um einen symbolischen oder festen Link handelt?
Was sind also ihre Beziehungen und Unterschiede? Jede Hilfe ist sehr willkommen!
Dieser Beitrag stammt aus einem früherenBeziehen sich sowohl die Ausgabe des Befehls „tty“ als auch die Datei „/dev/tty“ auf das Steuerterminal des aktuellen Bash-Prozesses?
Antwort1
Die tty
Manpage in Abschnitt 4behauptet Folgendes:
Die Datei/Entwickler/ttyist eine Zeichendatei mit der Hauptnummer 5 und der Nebennummer 0, normalerweise im Modus 0666 und der Besitzergruppe root.tty. Es ist ein Synonym für das Steuerterminal eines Prozesses, falls vorhanden.
In Ergänzung zu
ioctl(2)
Anfragen, die von dem Gerät unterstützt werden, auf das sich tty bezieht,ioctl(2)
AnfrageTIOCNOTTY
wird unterstützt.
TIOCNOTTY
Trennen Sie den aufrufenden Prozess von seinem Steuerterminal.
Wenn der Prozess der Sitzungsleiter ist, werden
SIGHUP
SignaleSIGCONT
an die Vordergrundprozessgruppe gesendet und alle Prozesse in der aktuellen Sitzung verlieren ihr steuerndes TTY.Das
ioctl(2)
Aufruf funktioniert nur bei Dateideskriptoren, die verbunden sind mit /Entwickler/tty. Es wird von Daemon-Prozessen verwendet, wenn sie von einem Benutzer an einem Terminal aufgerufen werden. Der Prozess versucht,/Entwickler/tty. Wenn das Öffnen erfolgreich ist, wird die Verbindung mithilfe von vom Terminal getrenntTIOCNOTTY
. Wenn das Öffnen fehlschlägt, ist die Verbindung offensichtlich nicht an ein Terminal angeschlossen und muss sich nicht trennen.
Dies würde teilweise erklären, warum /dev/tty
es keinen symbolischen Link zum steuernden Terminal gibt: es würde ein zusätzliches unterstützen ioctl
, und es könnte kein steuerndes Terminal geben (aber ein Prozess kann immer versuchen, darauf zuzugreifen /dev/tty
). Die Dokumentation ist jedoch falsch: Das zusätzliche ioctl
ist nicht nur zugänglichüber /dev/tty
(sehenmosvys Antwort, was auch eine sinnvollere Erklärung für die Natur von liefert /dev/tty
).
/dev/tty
kann verschiedene Steuerterminals darstellen, ohne eine Verbindung darzustellen, da der Treiber, der es implementiert, bestimmt, welches das Steuerterminal des aufrufenden Prozesses ist (sofern vorhanden).
Sie können sich das als /dev/tty
das Steuerterminal vorstellen, das somit Funktionen bietet, die nur für ein Steuerterminal sinnvoll sind, während /dev/pts/2
usw. einfache Terminals sind, von denen eines zufällig das Steuerterminal für einen bestimmten Prozess sein kann.
Antwort2
/dev/tty
ist ein „magisches“ Zeichengerät, das beim Öffnen einen Handle zum aktuellen Terminal zurückgibt.
Vorausgesetzt, dass das Steuerterminal ein ist , verweisen ein über und einer über geöffneter /dev/pts/1
Dateideskriptor auf dasselbe Gerät; alle Schreib-, Lese- oder anderen Dateivorgänge funktionieren auf beiden gleich./dev/pts/1
/dev/tty
Insbesondere akzeptieren sie den gleichen Satz von Ioctls und TIOCNOTTY
es gibt keinen zusätzlichen Ioctl, der nur über/dev/tty
.
ioctl(fd, TIOCNOTTY)
funktioniert bei jedem Dateideskriptor, der auf ein Terminal verweist, gleich, vorausgesetzt, dass es sich um das Steuerterminal des Prozesses handelt, der es aufruft.
/dev/tty
Es spielt keine Rolle, ob der Deskriptor durch Öffnen von , /dev/pts/1
, erhalten wurde /dev/ptmx
(in diesem Fall wird das ioctl auf sein entsprechendesSklave) oder in jüngerer Zeit durch einen Anruf an ioctl(master, TIOCGPTPEER, flags)
.
Beispiel:
$ cat <<'EOT' >tiocnotty.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(int ac, char **av){
if(ioctl(0, TIOCNOTTY)) err(1, "io(TIOCNOTTY)");
if(ac < 2) return 0;
execvp(av[1], av + 1);
err(1, "execvp %s", av[1]);
}
EOT
$ cc -W -Wall tiocnotty.c -o tiocnotty
$ ./tiocnotty
$ ./tiocnotty </dev/tty
$ tty
/dev/pts/0
$ ./tiocnotty </dev/pts/0
Außerdem wird der aktuelle Prozess dadurch nicht wirklich vom TTY „getrennt“. Der Prozess kann weiterhin davon lesen, ein Befehl ^C
auf dem Terminal beendet ihn usw. Die einzige Auswirkung auf einen Prozess, der kein Sitzungsleiter ist, besteht darin, dass das TTY nicht mehr über erreichbar ist /dev/tty
und in nicht mehr als steuerndes TTY aufgeführt wird /proc/PID/stat
:
$ ./tiocnotty cat
^C
$ ./tiocnotty cat
^Z
[2]+ Stopped ./tiocnotty cat
$ ./tiocnotty cat
foo
foo
^D
$ ./tiocnotty cat /dev/tty
cat: /dev/tty: No such device or address
$ ./tiocnotty awk '{print$7}' /proc/self/stat
0
[das 7. Feld /proc/<pid>/stat
ist die Geräte-ID des steuernden TTY, siehe proc(5)
]
Wenn der aufrufende Prozess der Sitzungsleiter ist, wird die Sitzung tatsächlich vom TTY getrennt und ein SIGHUP
/ SIGCONT
-Paar von der Sitzung an die Vordergrundprozessgruppe gesendet. Aber selbst dann wird das Terminalnichtgeschlossen werden, und der Prozess kann immer noch daraus lesen, wenn er Folgendes übersteht SIGHUP
:
$ script /dev/null -c 'trap "" HUP; exec ./tiocnotty cat'
Script started, file is /dev/null
lol
lol
^C^C^C^C^C # no controlling tty anymore
wtf
wtf
^D # but still reading fine from it
Script done, file is /dev/null
/dev/tty
ist kein symbolischer Link wie /dev/stdin
=> /dev/fd/0
=> /proc/self/fd/0
=>, /dev/pts/0
da es lange vor virtuellen dynamischen Dateisystemen wie procfs (und lange vor symbolischen Links im Allgemeinen) erfunden wurde. Und viele Programme sind von seiner besonderen Semantik abhängig geworden (z. B. /dev/tty
schlägt es fehl ENODEV
, wenn das Steuerterminal nicht zugänglich ist).