Tenho um dispositivo que envia informações por USB para o meu computador. Arch Linux configura este dispositivo criando um arquivo ttyUSB0
chamado /dev/
. Tenho usado GTKterm
para receber essas informações recebidas e exibi-las em uma janela de terminal emulada.
Minha pergunta é: como exatamente GTKterm
lê/grava nesse ttyUSB0
arquivo e onde posso começar a aprender como implementar funcionalidades semelhantes? Ou seja, na forma mais básica, como posso escrever um caractere ttyUSB0
ou, 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 tty
e 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 screen
ou xterm
, poderá executar run echo spooky > /dev/pts/2
nesse 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 -l
e 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.