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 a partir deles. Eles têm um comportamento especial diferente dos arquivos "comuns", mas o básico é o mesmo. Eu cobrirei alguns dos casos especiais no final, mas primeiro, um experimento.
Uma coisa interessante que você pode fazer direto de um terminal comum. Execute tty
e imprima uma linha como:
/dev/pts/2
Esse é o dispositivo TTY que seu terminal está executando. Você pode escrever algo para esse terminal:
$ echo Hello > /dev/pts/2
Hello
$
Você pode até ler:
$ read X < /dev/pts/2
hello
$ echo $X
hello
$
( read X
é sh's "lê uma linha de entrada padrão na variável X" comando; o < é usar / dev / pts / 2 como entrada padrão para o comando de leitura; o primeiro "hello" eu digitei, e o segundo foi impresso).
Se você abrir outro shell, digamos, usando screen
ou xterm
, poderá executar echo spooky > /dev/pts/2
nesse shell para que o texto apareça no 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 em C muito simples que faz exatamente o que você pediu, e escreve um único caractere em / dev / pts / 3, e então lê um único byte:
#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 que esteja conectado a um shell ou emulador de terminal terá um comportamento interessante, mas você deve receber algo de volta.
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ê com ls -l
e configuradas com chmod
: você precisa de permissão de leitura para abrir o arquivo, lê-lo e gravar permissão para gravar 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 forma que sempre.
No que diz respeito a escrever um programa para trabalhar com ele, você não precisa fazer muito especial. Você pode ver no exemplo que uma coisa que você não precisa fazer é fechar o arquivo toda vez para ter seus dados lidos pelo outro lado: os arquivos TTY agem como pipelines, apenas empurrando dados para dentro. Ambas as direções quando elas chegam. Quando eu escrevi o texto para o TTY, ele apareceu imediatamente, e quando eu li dele depois, não havia mais nada esperando por mim. Não é não como gravar em um arquivo regular onde os dados são salvos no disco - eles são passados imediatamente para o outro lado ou armazenados na memória até que alguém os leia.
Você pode usar a função selecione para poder fazer outras coisas enquanto aguarda o dispositivo para dizer alguma coisa, mas se você está feliz em apenas esperar que os dados cheguem, basta usar as leituras de bloqueio e deixar o SO fazer o levantamento.
Uma coisa a ter em mente é que pode haver um tamanho de buffer limitado no kernel, e se você escrever muitos dados de uma só vez, pode acabar bloqueando sem querer. Se isso for um problema, use IO sem bloqueio com open("/dev/...", O_RDWR | O_NONBLOCK)
. O princípio será o mesmo em ambos os sentidos.