Как читать / записывать на tty * устройство?

29

У меня есть устройство, которое отправляет информацию по USB на мой компьютер. Arch Linux настраивает это устройство, создавая файл с именем ttyUSB0в /dev/. Я использую, GTKtermчтобы получить эту входящую информацию и отобразить ее в эмулируемом окне терминала.

У меня вопрос, как именно GTKtermчтение и запись в этот ttyUSB0файл, и где я могу начать изучать, как реализовать аналогичные функции? То есть, в самой простой форме, как я могу записать символ ttyUSB0или, наоборот, получить байт и записать его в файл?

sherrellbc
источник
1
Попробуйте использовать кошку, чтобы читать и эхо, чтобы написать. «Все это файл» в unix :)
dchirikov
Вы можете попробовать открыть последовательную консоль на нем. screenможет сделать это, иminiterm
mikeserv
Я думал с точки зрения программного подхода. Если это так, и это действительно так просто (просто открыть и прочитать файл), вы бы просто написали бесконечный цикл, чтобы непрерывно открывать, читать, закрывать файл и обновлять, когда появляются новые данные с предыдущего раза? Что произойдет, если устройство 'tty' попытается записать файл, если он открыт в вашей программе?
sherrellbc
Может быть, это поможет: cmrr.umn.edu/~strupp/serial.html : open (), read (), write () и select (). Кажется, ничего особенного.
дчириков
@sherrellbc - вы можете писать сценарии screenи / или minitermпрограммно.
mikeserv

Ответы:

38

TTY - это файлы, которые вы можете использовать, как и любые другие. Вы можете открывать их с помощью стандартных инструментов открытия файлов на вашем языке и читать или писать из них. У них есть особое поведение, отличное от «обычных» файлов, но основы те же. Я расскажу о некоторых особых случаях в конце, но сначала эксперимент.

Одна интересная вещь, которую вы можете сделать прямо с обычного терминала. Запустите, ttyи он напечатает строку вроде:

/dev/pts/2

Это устройство TTY, на котором работает ваш терминал. Вы можете написать что-нибудь для этого терминала:

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

Вы даже можете прочитать из него:

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

( read Xэто команда sh «прочитать строку из стандартного ввода в переменную X»; <означает использование / dev / pts / 2 в качестве стандартного ввода для команды чтения; первое «привет», которое я напечатал, а второе было распечатано) ,

Если вы откроете другую оболочку, скажем, с помощью screenили xterm, вы можете запустить run echo spooky > /dev/pts/2в этой оболочке, чтобы текст появился на вашем исходном терминале, и то же самое для других команд. Все это только ваша оболочка, открывающая файл, не зная, что это TTY.


Вот очень простая программа на C, которая выполняет только то, что вы просили, записывает один символ в / dev / pts / 3 и затем читает из него один байт:

#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;
}

Реальное устройство TTY, подключенное к эмулятору оболочки или терминала, будет иметь интересное поведение, но вы должны получить что-то обратно.


Для доступа к терминалу вам необходимо иметь разрешение на его использование. Это просто стандартные права доступа к файлам, которые вы видите ls -lи устанавливаете с помощью chmod: вам нужно разрешение на чтение, чтобы открыть файл и прочитать его, и разрешение на запись для записи в него. TTY, которые поддерживают ваш терминал, будут принадлежать вам, а TTY другого пользователя - нет, а TTY для USB-устройств могут быть или не быть, в зависимости от вашей конфигурации. Вы можете изменить разрешения так же, как всегда.

Что касается написания программы для работы с ней, вам не нужно делать ничего особенного. В примере вы можете видеть, что вам не нужно закрывать файл каждый раз, когда ваши данные читаются на другом конце: файлы TTY действуют как конвейеры, просто толкая данные в обоих направлениях по мере их поступления. Когда я написал текст в TTY, он появился сразу, а когда я прочитал его позже, меня уже ничего не ждали. Это не то же самое, что запись в обычный файл, где данные сохраняются на диске - они сразу передаются на другую сторону или сохраняются в памяти, пока кто-то их не прочитает.

Возможно, вы захотите использовать функцию выбора, чтобы вы могли делать другие вещи, пока вы ожидаете, что устройство что-то скажет, но если вы просто хотите дождаться поступления данных, вы можете просто использовать блокировку чтения и позволить ОС делать это. подъем.

Следует иметь в виду, что в ядре может быть ограниченный размер буфера, и если вы пишете много данных одновременно, блокировка может оказаться бессмысленной. Если это может быть проблемой, используйте неблокирующий ввод-вывод с open("/dev/...", O_RDWR | O_NONBLOCK). Принцип будет одинаковым в любом случае.

Майкл Гомер
источник
Я пытаюсь, sudo echo Hello > /dev/tty4когда я нахожусь в среде рабочего стола, но я получаю, bash: /dev/tty4: Permission deniedесли я не вошел в tty4. Однако, если я вошел в tty4, все работает нормально. Что является причиной этого?
Утку
@ Utku, это, безусловно, какая-то проблема с разрешениями, которые удаляются после аутентификации на виртуальном терминале. Проверьте права доступа к файлам до и после входа в систему.ls -l /dev/tty4
sherrellbc
1
> /dev/tty4часть IST не является часть echoподпроцесса начатого , sudoно частью sudoсамого процесса, который выполняется для текущего пользователя. Права доступа к файлу для текущего пользователя применяются вместо root.
Robin479