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처리 중에 문자를 삭제해야 합니다.
- 입력 시 특수 문자인 경우이카논플래그가 설정되었습니다. 수신되면 읽기를 기다리는 모든 바이트는 개행 문자를 기다리지 않고 즉시 프로세스에 전달됩니다.EOF버려진. 그래서 기다릴 바이트가 없다면(그건EOF줄의 시작 부분에 발생)
그러나 표준 터미널로 작업하는 것이 아닙니다. 푸시할 바이트가 최소 1바이트 이상 있는 한 모든 리더(요청 시)에 모든 데이터를 푸시하는 터미널로 작업하고 있는 것입니다. 터미널은 입력을 한 줄씩 버퍼링하지 않으므로 EOF 바이트를 널 읽기로 대체할 수 없습니다. 대신 해당 바이트를 푸시하여 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
데이터 끝에 개행 문자를 유지하는 것입니다.)