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

questionAnswers(2)

yourAnswerToTheQuestion