cat no shell não termina na recepção do EOT através da porta serial

2

Eu tenho o script shell / perl que inicia os comandos cat para receber dados seriais recebidos de um dispositivo externo.

O dispositivo externo é projetado para enviar um caractere EOT quando a transmissão é concluída. Mas o comando cat nunca termina ao receber EOT, na verdade ele imprime todos os dados seriais, seguidos pela caixinha com (0004) que é o valor hexadecimal para EOT.

Quando canalizo todos esses dados para o arquivo e os abro no VIM, vejo o caractere EOT representado por ^ D.

Eu gostaria de saber por que o comando cat no terminal não detectaria o EOT?

EDITAR: stty --all --file = (serial_port) yeilds

velocidade 115200 baud; linhas 0; colunas 0; linha = 0; intr = ^ C; quit = ^ \; apagar = ^; kill = ^ U; eof = ^ D; eol =; eol2 =; swtch =; start = ^ Q; stop = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; flush = ^ O; min = 1; tempo = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -cdtrdsr -ignbrk -brkint -ignpar -parmrk -inpck -istrip -incr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -dois nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -executado -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -keke

    
por seek 03.04.2015 / 01:03

2 respostas

1

CTRL + D não tem sentido aqui - é apenas outro byte. Isso ocorre porque seu terminal serial não está configurado para lidar com isso. Especificamente, você está efetivamente em modo bruto , ou Modo de entrada não-canônico . Veja o sinal -icanon na sua saída stty -a ? Isso aperta isso. Veja como o POSIX descreve um terminal que deve considerar um caractere EOF:

  • EOF
    • Caractere especial na entrada, que é reconhecido se o sinalizador ICANON estiver definido. Quando recebidos, todos os bytes que estão aguardando serem lidos são imediatamente passados para o processo sem esperar por uma nova linha, e o EOF é descartado. Assim, se não houver bytes esperando (ou seja, o EOF ocorreu no início de uma linha) , uma contagem de bytes de zero deve ser retornada da read() , representando uma indicação de final de arquivo. Se ICANON estiver definido, o caractere EOF será descartado quando processado.

Mas você não está trabalhando com um terminal canônico - você está trabalhando com um terminal que enviará qualquer / todos os dados para qualquer leitor, se solicitado, desde que haja pelo menos um byte para ser pressionado. O terminal não armazena em buffer entrada por linha - e, portanto, não pode substituir o byte EOF por uma leitura vazia - em vez disso, ele simplesmente envia o byte, o que, para cat , apenas incentiva a leitura.

  • Se ICANON for definido, o processamento canônico será habilitado. Isso habilita as funções de edição erase e kill e a montagem de caracteres de entrada em linhas delimitadas por NL , EOF e EOL , conforme descrito em Processamento de entrada do modo canônico .

  • Se ICANON não estiver definido, as solicitações de leitura serão atendidas diretamente a partir da fila de entrada. Uma leitura não será satisfeita até que pelo menos MIN bytes tenham sido recebidos ou que o valor de tempo limite TIME tenha expirado entre os bytes. O valor do tempo representa décimos de segundo. Consulte Processamento de entradas no modo não-canônico para obter mais detalhes.

por 03.04.2015 / 20:20
1

O caractere EOT não marca o final de um arquivo. Um arquivo pode conter bytes arbitrários.

Digitar Ctrl + D em um terminal faz com que o aplicativo pense que o final do arquivo chegou. O aplicativo não lê um caractere Ctrl + D (EOT), ele vê uma indicação de fim de arquivo. A interpretação de Ctrl + D como caractere de fim de entrada é executada pelo driver de terminal no kernel; Ele pode ser personalizado com o comando stty (por exemplo, stty eof ^E para alterar o caractere ou stty eof ^- para desativar o recurso). Isso é específico para terminais, não se aplica a arquivos regulares, a pipes, a dispositivos que não são terminais, etc. Em particular, não se aplica a portas seriais.

Não há nenhum utilitário de shell padrão que interrompa a leitura na EOT ou em um caractere configurável e aceite entrada binária arbitrária. Se não houver bytes nulos em sua entrada, você poderá usar o comando head ou o read shell incorporado para ler uma linha depois de trocar EOT por EOL:

data=$(tr '
data=$(tr '%pre%42' '2%pre%4' | head -n 1 | tr '%pre%42' '2%pre%4'; echo a)
data=${data#a}
42' '2%pre%4' | head -n 1 | tr '%pre%42' '2%pre%4'; echo a) data=${data#a}

(O a extra é para garantir que as novas linhas no final dos dados sejam preservadas.)

    
por 03.04.2015 / 01:31