Teste de loopback / duplex de porta serial, em Bash ou C? (substituição de processo)
Eu tenho um dispositivo serial configurado como loopback (o que significa que ele simplesmente fará eco a qualquer caractere recebido) e gostaria de medir a velocidade efetiva da taxa de transferência. Para isso, eu esperava poder usartime
, como em
time bash -c '...'
Onde '...
'seria algum comando que eu poderia executar.
Agora, o primeiro problema é que eu quero usar o dispositivo em 2000000 bps, então não posso usarttylog outela (ambos parecem subir apenas para 115.200 bps). No entanto, trabalhando com/dev/ttyUSB0
como um arquivo (usando o redirecionamento de arquivo ecat
) parece funcionar bem:
# initialize serial port
stty 2000000 -ixon icanon </dev/ttyUSB0
# check settings
stty -a -F /dev/ttyUSB0
# in one terminal - read from serial port
while (true) do cat -A /dev/ttyUSB0 ; done
# in other terminal - write to serial port
echo "1234567890" > /dev/ttyUSB0
# back to first terminal, I now have:
# $ while (true) do cat -A /dev/ttyUSB0 ; done
# 1234567890$
# ...
Agora, eu gostaria de fazer algo semelhante - eu gostaria decat
um arquivo para uma porta serial e a porta serial seja lida novamente - mas a partir de um único comando de terminal (para que eu pudesse usá-lo como argumento paratime
)
Eu pensei que poderia usar uma substituição do processo Bash, para que a parte "escrita" e "leitura" fosse executada, mais ou menos, em "paralelo" - se eu tentar com pipes nomeados, funcionará:
# mkfifo my.pipe # same as below:
$ mknod my.pipe p
$ comm <(echo -e "test\ntest\ntest\n" > my.pipe) <(cat my.pipe)
test
test
test
comm: file 2 is not in sorted order
Lá em cima, não estou usandocomm
para qualquer outra finalidade, além de (meio que) mesclar os dois processos em um único comando (eu acho, eu poderia ter usado tão bemecho
em vez de).
Infelizmente, esse truque não parece funcionar com uma porta serial, porque, quando eu tento, às vezes recebo:
$ comm <(echo "1234567890" > /dev/ttyUSB0) <(while (true) do cat -A /dev/ttyUSB0 ; done)
cat: /dev/ttyUSB0: Invalid argument
..., no entanto, geralmente não recebo nenhuma saída. Isso me diz o seguinte: ou não há controle sobre qual processo inicia primeiro e, portanto,cat
pode começar a ler antes que a porta esteja pronta (no entanto, isso não parece ser um problema no primeiro exemplo acima); ou no Linux / Bash, você não pode ler e gravar em uma porta serial ao mesmo tempo; portanto, o "Invalid argument
"ocorreria nos momentos em que a leitura e a gravação pareciam acontecer ao mesmo tempo.
Então, minhas perguntas são:
Existe uma maneira de fazer algo assim (cat
um arquivo para uma porta serial configurada como loopback; leia-o novamente e veja quanto tempo leva) apenas no Bash, sem recorrer a escrever um programa C dedicado?Se eu precisar de um programa C dedicado, algum exemplo de fonte disponível na rede eu poderia usar?Muito obrigado por quaisquer respostas,
Felicidades!
EDIT: Estou ciente de que owhile
o loop escrito acima não sai; essa linha de comando foi para testes preliminares e eu a interrompo usando Ctrl-C. (Eu poderia, em princípio, interrompê-lo com algo comotimeout -9 0.1 bash -c 'while (true) do echo AA ; done'
, mas isso derrotaria o objetivo detime
, então :) )
A razão quewhile
está lá, é que, por enquanto, lendo viacat
do dispositivo sai imediatamente; às vezes euter configure o dispositivo para que, quandocat
emitido, ele de fato bloqueia e aguarda os dados recebidos; mas ainda não consigo entender o que está acontecendo (e parcialmente é por isso que estou procurando uma maneira de testar a partir da linha de comando).
Caso não tenha usado owhile
, Imagino que, para o tempo, eu usaria algo como:
time bash -c 'comm <(echo "1234567890" > /dev/ttyUSB0) <(cat -A /dev/ttyUSB0)'
... no entanto, para que isso funcione, mais ou menos, assume quecat -A /dev/ttyUSB0
começa primeiro e bloqueia; então oecho
escreve na porta serial (e sai); e depoiscat -A
produz o que lê da porta serial - e sai. (E não tenho muita certeza nem se uma porta serial pode se comportar dessa maneira, nem secat
pode ser feito para bloquear e sair arbitrariamente assim)
O método exato realmente não importa; se possível, eu gostaria de evitar codificar meu próprio programa C para fazer esse tipo de teste - e é por isso que meu principal interesse é se é possível, de alguma maneira, executar um "teste full-duplex" usando o básico Bash / Linux (ou seja,coreutils
); (e se não, se houver um código pronto que eu possa usar para algo como isto)
EDIT2: Também possivelmente relevante:
Processos paralelos no Bash - Fóruns do Ubuntu