Wie kann ich auf einem tty * -Gerät lesen / schreiben?

29

Ich habe ein Gerät, das Informationen über USB an meinen Computer sendet. Arch Linux richtet dieses Gerät ein, indem es eine Datei mit dem Namen ttyUSB0in erstellt /dev/. Ich habe verwendet GTKterm, um diese eingehenden Informationen zu empfangen und in einem emulierten Terminalfenster anzuzeigen.

Meine Frage ist, wie genau GTKtermliest / schreibt man in diese ttyUSB0Datei und wo kann ich lernen, wie man ähnliche Funktionen implementiert? Das heißt, in der einfachsten Form, wie kann ich ein Zeichen schreiben ttyUSB0oder im Gegensatz dazu ein Byte empfangen und in eine Datei schreiben?

sherrellbc
quelle
1
Versuchen Sie, mit cat zu lesen und mit echo zu schreiben. "Alles ist eine Datei" in Unix :)
dchirikov
Sie können versuchen, eine serielle Konsole darauf zu öffnen. screenkann dies tun, undminiterm
mikeserv
Ich habe programmatisch gedacht. Wenn dies zutrifft und es wirklich so einfach ist (die Datei nur zu öffnen und zu lesen), würden Sie dann einfach eine Endlosschleife schreiben, um die Datei fortlaufend zu öffnen, zu lesen, zu schließen und zu aktualisieren, wenn seit dem letzten Mal neue Daten vorliegen? Was passiert, wenn das 'tty'-Gerät versucht, in die Datei zu schreiben, wenn Sie sie in Ihrem Programm geöffnet haben?
Sherrellbc
Vielleicht hilft es: cmrr.umn.edu/~strupp/serial.html : open (), read (), write () und select (). Anscheinend nichts Besonderes.
Dchirikov
@sherrellbc - Sie können Skripte screenund / oder minitermProgramme erstellen .
mikeserv

Antworten:

38

TTYs sind Dateien, die Sie wie alle anderen verwenden können. Sie können sie mit den Standardwerkzeugen zum Öffnen von Dateien Ihrer Sprache öffnen und von diesen lesen oder schreiben. Sie haben ein spezielles Verhalten, das sich von "normalen" Dateien unterscheidet, aber die Grundlagen sind die gleichen. Ich werde am Ende einige der Sonderfälle behandeln, aber zuerst ein Experiment.

Eine interessante Sache, die Sie direkt von einem normalen Terminal aus erledigen können. Führen Sie ttyund es wird eine Zeile wie folgt gedruckt:

/dev/pts/2

Das ist das TTY-Gerät, auf dem Ihr Terminal ausgeführt wird. Sie können etwas auf dieses Terminal schreiben:

$ echo Hello > /dev/pts/2
Hello
$

Sie können sogar daraus lesen:

$ read X < /dev/pts/2
hello
$ echo $X
hello
$

( read XIst shs Befehl "Lese eine Zeile von der Standardeingabe in die Variable X"; das <soll / dev / pts / 2 als Standardeingabe für den Lesebefehl verwenden; das erste "Hallo", das ich eingegeben habe, und das zweite wurde ausgedruckt) .

Wenn Sie eine andere Shell öffnen, z. B. mit screenoder xterm, können Sie sie ausführen echo spooky > /dev/pts/2, damit der Text auf Ihrem ursprünglichen Terminal angezeigt wird, und dies gilt auch für die anderen Befehle. All dies ist nur Ihre Shell, die eine Datei öffnet, ohne zu wissen, dass es sich um ein TTY handelt.


Hier ist ein sehr einfaches C-Programm, das genau das tut, worum Sie gebeten haben. Es schreibt ein einzelnes Zeichen nach / dev / pts / 3 und liest dann ein einzelnes Byte zurück:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>    
int main() {
    char byte;
    int fd = open("/dev/pts/3", O_RDWR);
    write(fd, "X", 1);
    ssize_t size = read(fd, &byte, 1);
    printf("Read byte %c\n", byte);
    return 0;
}

Ein echtes TTY-Gerät, das an eine Shell oder einen Terminal-Emulator angeschlossen ist, weist dort ein interessantes Verhalten auf, aber Sie sollten etwas zurückbekommen.


Um auf ein Terminal zugreifen zu können, benötigen Sie die Berechtigung, es zu verwenden. Dies sind nur die Standard-Dateiberechtigungen, die Sie sehen ls -lund mit denen chmodSie festlegen : Sie benötigen eine Leseberechtigung, um die Datei zu öffnen und zu lesen, und eine Schreibberechtigung, um in sie zu schreiben. Die TTYs, die Ihr Terminal unterstützen, gehören Ihnen, die TTYs anderer Benutzer jedoch nicht. Je nach Konfiguration können TTYs für USB-Geräte verwendet werden. Sie können die Berechtigungen wie gewohnt ändern.

Was das Schreiben eines Programms anbelangt, müssen Sie nicht viel Besonderes tun. Sie können in dem Beispiel zu sehen , dass eine Sache , die Sie nicht brauchen , schließt jedes Mal der Datei zu tun ist , Ihre Daten mit dem anderen Ende gelesen haben: wirken die TTY - Dateien wie Pipelines, nur Daten in beiden Richtungen schieben , wie es kommt. Als ich dem TTY einen Text schrieb, erschien er sofort, und als ich ihn später las, wartete schon nichts mehr auf mich. Es ist nicht so, als würde man in eine normale Datei schreiben, in der die Daten auf der Festplatte gespeichert werden. Sie werden sofort an die andere Seite weitergeleitet oder im Speicher gespeichert, bis jemand sie liest.

Möglicherweise möchten Sie die Auswahlfunktion verwenden, damit Sie andere Aktionen ausführen können, während Sie darauf warten, dass das Gerät etwas sagt. Wenn Sie jedoch nur darauf warten, dass Daten eingehen, können Sie einfach blockierende Lesevorgänge verwenden und das Betriebssystem dies tun lassen das Heben.

Eine Sache, die Sie beachten sollten, ist, dass der Kernel möglicherweise eine begrenzte Puffergröße hat. Wenn Sie viele Daten auf einmal schreiben, kann dies zum Blockieren führen, ohne dass dies eine Bedeutung hat. Wenn dies wahrscheinlich ein Problem ist, verwenden Sie nicht blockierende E / A mit open("/dev/...", O_RDWR | O_NONBLOCK). Das Prinzip wird in beiden Fällen dasselbe sein.

Michael Homer
quelle
Ich versuche es sudo echo Hello > /dev/tty4in der Desktop-Umgebung, erhalte aber, bash: /dev/tty4: Permission deniedwenn ich nicht bei tty4 angemeldet bin. Wenn ich jedoch bei tty4 angemeldet bin, funktioniert alles einwandfrei. Was ist der Grund dafür?
Utku
@Utku, das ist sicherlich eine Art Berechtigungsproblem, das nach der Authentifizierung mit dem virtuellen Terminal behoben wird. Überprüfen Sie die Dateiberechtigungen, bevor und nachdem Sie sich angemeldet haben.ls -l /dev/tty4
sherrellbc
1
Der > /dev/tty4Teil ist nicht Teil des echoTeilprozesses , der vom aktuellen Benutzer ausgeführt wird, sudosondern Teil des sudoProzesses. Dateiberechtigungen für den aktuellen Benutzer gelten anstelle von root.
Robin479