Cat

shell中的cat命令在通過串口接收EOT時不會終止

  • August 5, 2020

我有 shell/perl 腳本,它啟動cat從外部設備接收傳入串列數據的命令。

外部設備設計為在完成傳輸時發送 EOT 字元。但是該cat命令在收到 EOT 後永遠不會終止,實際上它會列印出所有的串列數據,然後是帶有 (0004) 的小框,它是 EOT 的十六進制值。

當我將所有這些數據通過管道傳輸到文件中並在 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

CTRL+D 在這裡毫無意義——它只是另一個字節。這是因為您的串列終端未配置為處理它。具體來說,您實際上處於raw-modeNon-Canonical Input Mode。看到輸出中的-icanon標誌了stty -a嗎?那收緊它。以下是 POSIX 描述終端應考慮 EOF 字元的方式:

  • EOF
    • 輸入的特殊字元,如果設置了ICANON標誌,則可以辨識。收到後,所有等待讀取的字節立即傳遞給程序,無需等待換行符,EOF被丟棄。因此,如果沒有等待的字節*(即,EOF發生在行的開頭),則應從 中返回字節計數為零read(),表示文件結束指示。如果設置了ICANON*,則處理時應丟棄EOF字元。

但是您不是在使用規範終端工作 - 您正在使用一個終端,只要有至少一個字節要推送,就會在被詢問時將任何/所有數據推送給任何閱讀器。終端不會按行緩衝輸入 - 因此它不能用空讀取替換 EOF 字節 - 相反,它只是推送字節,這cat只會鼓勵它繼續閱讀。

  • 如果設置了 ICANON,則應啟用規範處理。這啟用了擦除終止編輯功能,並將輸入字元組合成由NLEOFEOL分隔的行,如規範模式輸入處理中所述。
  • 如果未設置ICANON,則應直接從輸入隊列滿足讀取請求。在至少接收到MIN個字節或字節之間的超時值TIME到期之前,不應滿足讀取。時間值表示十分之一秒。有關詳細資訊,請參閱非規範模式輸入處理

引用自:https://unix.stackexchange.com/questions/194120