シリアルポートを介してEOTを受信すると、シェルのcatコマンドは終了しません。

シリアルポートを介してEOTを受信すると、シェルのcatコマンドは終了しません。

cat外部デバイスから着信シリアルデータを受信するコマンドを実行するシェル/パールスクリプトがあります。

外部デバイスは、転送が完了した後にEOT文字を送信するように設計されています。ただし、catコマンドはEOTを受信した後は決して終了しません。実際、すべてのシリアルデータとEOTの16進値(0004)を持つ小さなボックスが印刷されます。

これらすべてのデータをファイルにパイプしてVIMで開くと^D

端末のcatコマンドがなぜEOTを検出しないのか疑問に思います。

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

speed 115200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany
-imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl
-echoke

答え1

CTRL+D はここでは何の意味もありません。もう一つのバイトです。これは、シリアル端末がそれを処理するように構成されていないためです。特に、あなたは実際にオリジナルモードまたは非標準入力モード。出力-icanonにフラグが表示されますstty -aか?それはすべてです。 POSIXが端末がEOF文字を考慮する必要がある方法を説明する方法は次のとおりです。

  • EOF
    • 入力時に特殊文字の場合イカノンフラグがセットされました。受信されると、読み取りを待つすべてのバイトは改行文字を待たずにすぐにプロセスに渡されます。EOF放棄されました。だから待つバイトがなければ(それはEOF行の先頭に発生)read()、ファイルの終わりを示すバイト数0を返す必要があります。もしイカノン設定後、EOF処理中に文字を削除する必要があります。

しかし、標準的な端末で作業するのではありません。プッシュするバイトが少なくとも1バイト以上ある限り、すべてのリーダー(要求時)にすべてのデータをプッシュする端末で作業しているのです。端末は入力を1行ずつバッファリングしないため、EOFバイトをNULL読み取りに置き換えることはできません。代わりに、対応するバイトをプッシュして引き続きcat読み取りのみをお勧めします。

  • もしイカノン一度設定したら、正式な処理を有効にする必要があります。これは作る削除そして殺す機能を編集して入力文字をオランダEOF廃止で説明されているように通常モード入力処理

  • もしイカノン設定されていない場合、読み取り要求は入力キューで直接満たす必要があります。少なくともそれまで最小受信バイトまたはタイムアウト値時間バイト間で有効期限が切れます。時間値は10分の1秒を表します。バラより非正規モード入力処理詳細については。

答え2

EOT文字はファイルの終わりを表示しません。ファイルには任意のバイトを含めることができます。

Ctrl+を入力D ターミナルからアプリケーションは、ファイルが終了したと思うようにします。アプリケーションはCtrl + D(EOT)文字を読み取らず、代わりにファイルの終わりの表示を表示します。 Ctrl+D を入力終了文字として解釈することは、カーネルのターミナルドライバによって行われます。sttyコマンドを使用してカスタマイズできます(stty eof ^E文字の変更やstty eof ^-機能の無効化など)。これは端末によって異なり、通常のファイル、パイプ、非端末装置などでは機能しません。特にシリアルポートでは動作しません。

EOTまたは設定可能な文字の読み取りを停止し、任意のバイナリ入力を可能にする標準のシェルユーティリティはありません。入力にヌルバイトがない場合は、コマンドheadまたは組み込みシェルを使用してEOTをEOLに交換してから行を読み取ることができますread

data=$(tr '\004\012' '\012\004` | head -n 1 | tr '\004\012' '\012\004`; echo a)
data=${data#a}

(追加は、aデータの末尾に改行文字を保持することです。)

関連情報