Como ler/gravar no dispositivo tty*?

Como ler/gravar no dispositivo tty*?

Tenho um dispositivo que envia informações por USB para o meu computador. Arch Linux configura este dispositivo criando um arquivo ttyUSB0chamado /dev/. Tenho usado GTKtermpara receber essas informações recebidas e exibi-las em uma janela de terminal emulada.

Minha pergunta é: como exatamente GTKtermlê/grava nesse ttyUSB0arquivo e onde posso começar a aprender como implementar funcionalidades semelhantes? Ou seja, na forma mais básica, como posso escrever um caractere ttyUSB0ou, em contraste, receber um byte e gravá-lo em um arquivo?

Responder1

TTYs são arquivos que você pode usar como qualquer outro. Você pode abri-los com as ferramentas padrão de abertura de arquivos do seu idioma e ler ou escrever neles. Eles têm algum comportamento especial diferente dos arquivos "comuns", mas o básico é o mesmo. Abordarei alguns casos especiais no final, mas primeiro, um experimento.

Uma coisa interessante que você pode fazer diretamente de um terminal normal. Execute ttye imprimirá uma linha como:

/dev/pts/2

Esse é o dispositivo TTY no qual seu terminal está sendo executado. Você pode escrever algo nesse terminal:

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

Você pode até ler:

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

( read Xé o comando sh "ler uma linha da entrada padrão na variável X"; o < é usar /dev/pts/2 como entrada padrão para o comando de leitura; o primeiro "olá" eu digitei e o segundo foi impresso) .

Se você abrir outro shell, digamos, usando screenou xterm, poderá executar run echo spooky > /dev/pts/2nesse shell para fazer o texto aparecer em seu terminal original, e o mesmo para os outros comandos. Tudo isso é apenas o seu shell abrindo um arquivo sem saber que é um TTY.


Aqui está um programa C muito simples que faz exatamente o que você pediu e grava um único caractere em /dev/pts/3 e depois lê um único byte dele:

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

Um dispositivo TTY real conectado a um shell ou emulador de terminal terá um comportamento interessante, mas você deverá receber algo em troca.


Para acessar um terminal você precisa ter permissão para usá-lo. Essas são apenas as permissões de arquivo padrão que você vê ls -le define chmod: você precisa de permissão de leitura para abrir o arquivo e lê-lo, e permissão de gravação para escrever nele. Os TTYs que suportam o seu terminal serão de sua propriedade, mas o TTY de outro usuário não, e os TTYs para dispositivos USB podem ou não ser, dependendo da sua configuração. Você pode alterar as permissões da mesma maneira de sempre.

No que diz respeito a escrever um programa para funcionar com ele, você não precisa fazer muita coisa especial. Você pode ver no exemplo que uma coisa que vocênãoO que você precisa fazer é fechar o arquivo sempre para que seus dados sejam lidos na outra extremidade: os arquivos TTY agem como pipelines, apenas empurrando os dados em ambas as direções conforme eles chegam. Quando escrevi um texto no TTY, ele apareceu imediatamente, e quando Eu li depois que não havia nada esperando por mim. Isso énãocomo gravar em um arquivo normal onde os dados são salvos no disco - eles são repassados ​​imediatamente para o outro lado ou armazenados na memória até que alguém os leia.

Você pode querer usar oselecionefunção para que você possa fazer outras coisas enquanto espera o dispositivo dizer algo, mas se você estiver feliz em apenas esperar a chegada dos dados, você pode simplesmente usar leituras de bloqueio e deixar o sistema operacional fazer o levantamento.

Uma coisa a ter em mente é que pode haver um tamanho de buffer limitado no kernel e, se você gravar muitos dados de uma vez, poderá acabar bloqueando sem querer. Se isso for um problema, useIO sem bloqueiocom open("/dev/...", O_RDWR | O_NONBLOCK). O princípio será o mesmo de qualquer maneira.

informação relacionada