web-dev-qa-db-ja.com

echoとcatを使用したシリアルループバックの予期しない結果

したがって、TxからRxへのワイヤを実行するだけでループバックされる標準のRS232シリアルポートがあります。私は2つの別々の端末でechocatを実行してループバックをテストしています。

cat /dev/ttyS1
echo "hi" > /dev/ttyS1

私の問題は出力です。猫が走っているターミナルで「こんにちは」が戻ってくるのを期待していますが、代わりに次のようになります。

hi
[2 newlines]
hi
[4 newlines]
hi
[8 newlines]
hi
[16 newlines]
hi
[32 newlines]
hi

...など、私まで ctrl+ccat

Catを中断した後、もう一度実行すると、echoを2回実行するまで「hi」が出力されません。

これは正常ですか?なぜ私はこの動作を見ているのですか?

編集:改行とは、ASCII 0x0A。この出力にはキャリッジリターンはありません。

20
Kristina

ブルースの2回目のコメントのおかげで、私は自分で問題を理解することができました。

stty -a -F /dev/ttyS1を実行した後、問題の原因であることが判明した3つのオプションがありました。「echo」、「onlcr」、および「icrnl」です。

このシリアルポートはそれ自体にループバックされるので、echo "hi" > /dev/ttyS1を実行した後に何が起こったかを次に示します。

  1. echoコマンドは、デフォルトでメッセージの最後に改行を追加するため、 "hi" + LFが/ dev/ttyS1に送信されます
  2. 「onlcr」が設定されていたため、シリアルデバイスはLF=をCRLFに変換したため、Tx回線から送信された物理メッセージは「hi」+ CRLFでした。
  3. 「icrnl」が設定されていたため、Rxラインで受信された物理メッセージはCRをLFに変換しました。したがって、「cat」が出力するメッセージは「hi」+ LFLFでした。
  4. 「echo」が設定されていたため、Rxで受信されたメッセージ(「hi」+ LFLF)は、Tx回線で送り返されました。
  5. Onlcrにより、「hi」+ LFLFは「hi」+ CRLFCRLFになります。
  6. Icrnlにより、 "hi" + CRLFCRLFは "hi" + LFLFLFLFになりました
  7. エコーのため、 "hi" + LFLFLFLFがTxに送信されました

等々...

この問題を修正するために、次のコマンドを実行しました。

stty -F /dev/ttyS1 -echo -onlcr

"echo"を無効にすると、メッセージの無限ループが防止され、 "onlcr"を無効にすると、シリアルデバイスがLFを出力でCRLFに変換することを防止できます。これで、catは1つの「hi」を受け取ります(改行は1つです)。 echoを実行するたびに。

CR =キャリッジリターン(ASCII 0x0D); LF =ラインフィードまたは改行(ASCII 0x0A)

22
Kristina

テストのためにファイルをシリアルttyに連結する場合にも同様の問題がありました。受け入れられた答えに加えて:

次のようなことを行ってシリアル出力をテストしている場合:cat somefile.txt > /dev/ttyS0、正確なバイト値をテストしている場合、予期しないバイトデータが大量に含まれます。

sttyを使用すると、簡単なstty raw -F /dev/ttyS0は、端末による文字の挿入/置換を停止します(例:[...] 0x0A [...]-> [...] 0x0D 0x0A [...])。 rawフラグは端末のモードを変更するため、入出力処理は実行されません。

4
ineedtosleep