cat
텍스트 파일의 내용을 조정 하면 모든 내용이 인쇄되고 명령이 종료됩니다. 그러나 그렇게 하면 cat /dev/ttyS0
명령이 중단되고 새 데이터가 도착할 때까지 기다립니다.
이렇게 일시 중지되는 이유는 무엇입니까?
답변1
cat
터미널에서 실험
cat
더 많은 데이터를 기다리는 이유는 다음과 같습니다.쿠엥무 라고. 입력이 터미널이 되도록 입력 cat
하고 눌러도 동일한 일이 발생합니다. Enter터미널에서 동작을 쉽게 실험해 볼 수 있습니다 cat
. 먼저, 수행 방법은 다음과 같습니다.
터미널에 Ctrl+를 입력하면 D터미널은 리터럴 Ctrl+ D문자를 프로그램에 보내지 않습니다. 이렇게 하려면 Ctrl+ 를 입력하여 V다음 제어 문자를 문자 그대로 처리해야 함을 터미널에 알리고 Ctrl+ 를 입력해야 합니다 D. 대신에:
- 입력 버퍼에 텍스트가 있는 경우(즉, 아직 프로그램에 전송되지 않은 텍스트를 입력한 경우) 버퍼가 플러시됩니다. 이는 해당 텍스트가 프로그램에 전송되었음을 의미합니다. 프로그램은 다음에 읽을 때 이를 수신합니다.
- 입력 버퍼에 텍스트가 없으면 터미널은 프로그램에 입력의 끝을 나타내며, 이로 인해 프로그램은 다음 읽기 작업에서 파일 끝 조건에 직면하게 됩니다. 이는 실제로(아래 참조)입니다.현재의이 경우 읽기 작업은
cat
이미 읽고 있기 때문입니다.
Enter지시사항 제외 누르기개행 문자,반품Ctrl+를 누르지 않아도 버퍼가 플러시됩니다 D. 그러므로 당신은 다음을 관찰하게 될 것입니다:
텍스트를 입력하고 Enter또는 Ctrl+를 누르면 동일한 텍스트가 터미널에 기록 D됩니다 . 를
cat
사용하면 Enter개행cat
문자도 작성됩니다.Enter줄 시작 부분에서 누르거나 Ctrl+ 를 누른 후 D개행 문자를 보내고
cat
씁니다.줄의 시작 부분에서 +를 누르 Ctrl거나 +를 누른 후(즉, 두 번 연속) 입력을 종료합니다.DCtrlD
cat
마지막 입력 소스에서 읽을 내용이 없다는 것을 확인하면("cat"은 "catenate" 또는 "concatenate"를 의미하며, 이는 여러 파일 이름 인수를 받을 때 작동하는 방식입니다) 종료됩니다 .
제어 터미널에서 읽을 때 완료될 때까지 입력을 기다리는 것과 마찬가지로 cat
, 읽도록 지시하면 다른 파일이나 장치(직렬 터미널 포함)에서 추가 입력을 기다립니다.
CtrlD+ 및 와 관련된 특별한 동작 으로 인해 Enter입력이 로 전송됩니다 cat
.당신의 터미널, 대신에 cat
. 특히, cat
그 자체로는 개행문자를 특별히 취급하지 않습니다.
대기 프로세스 상태
cat
입력을 기다리는 동안 다른 터미널에서 상태를 확인해 보세요.
대부분의 Unix 계열 운영 체제에서는 pidof cat
또는 를 실행하여 실행 중인 모든 cat 프로세스의 프로세스 ID를 찾을 수 있습니다 pgrep -x cat
. 적어도하나일반적으로 지원됩니다. 또는 실행 중인 동일한 터미널에서 +를 눌러 Ctrl일시 중지합니다.Zcat
실제로프로세스를 일시 중지한 다음 실행하여 ps
PID를 찾은 다음 를 실행하여 다시 시작합니다 fg
. 또는 tty
첫 번째 터미널에서 실행하여 터미널 장치의 경로 이름을 표시합니다. GNU/Linux에서는 다음과 같을 수 있습니다. /dev/tty2
또는 /dev/pts/4
--then run cat
, 두 번째 터미널에서 실행, 교체ps -t tty
tty
tty
첫 번째 터미널의 출력입니다.
두 번째 터미널에서 교체한 곳을 실행하세요.ps pid
pid
cat 프로세스의 실제 프로세스 ID를 사용합니다. 상태를 표시하는 열을 포함하여 프로세스가 나열됩니다. (위 코드를 실행했더라도 tty -t
이전에 상태 열이 포함되지 않았던 GNU/Linux를 포함한 일부 시스템에서는 이 작업이 필요합니다.)
예를 들어 GNU/Linux 시스템에서는 다음과 같이 합니다.
ek@Io:~$ ps 30196
PID TTY STAT TIME COMMAND
30196 pts/4 S+ 0:00 cat
당신의 모습은 다르게 보일 수 있습니다. STAT 또는 S 열 아래에 나타나는 프로세스 상태 코드를 실행하여 찾는 것이 좋습니다 man ps
. 이러한 코드는 시스템마다 조금씩 다릅니다. 해당 GNU/Linux 시스템에서는참고(1)표시 프로세스의 상태는 다음과 같이 보고되었습니다.
S interruptible sleep (waiting for an event to complete)
+ is in the foreground process group
해당 GNU/Linux 시스템에서 위와 같이 + 를 cat
사용 하여 실행한 다음 Ctrl일시 중지 하면 다음으로 변경됩니다 .ZS+
T
T stopped by job control signal
수면은 방해받을 수 있으므로논스톱잠? 예:
D uninterruptible sleep (usually IO)
이는 일반적으로 프로세스가 커널이 취소를 허용하지 않는 IO 작업을 수행할 때 발생합니다. 중단 없이 절전 상태에 있는 프로세스는 종료할 수 없습니다. 또는를 사용하면 작업이 완료되면 TERM 또는 KILL 신호를 각각 수신하게 됩니다.kill pid
kill -9 pid
추적 프로세스
gdb
일반적으로 프로그램을 디버그하려면 또는 와 같은 디버거에서 프로그램을 엽니다 lldb
. 그러나 GNU/Linux를 포함한 일부 시스템에는 strace
다음 과 같은 프로그램이 있습니다.시스템 호출프로세스가 진행되고 있습니다. 터미널에서 입력을 기다리는 프로세스를 실행하는 데 를 사용하면 터미널의 프로세스에 더 많은 입력이 전송될 때까지 실행을 차단하는 strace
각 호출을 볼 수 있습니다 . read
Fedora, CentOS, Debian 또는 Ubuntu와 같은 GNU/Linux 시스템이 있는 경우(이들은 예시일 뿐이고 다른 시스템도 많이 있음) 다음 명령을 실행해 보세요.
strace cat
일련의 시스템 호출을 볼 수 있습니다. 먼저 프로세스를 실행하는 호출( execve
프로그램이 공유 라이브러리를 사용하는 경우 파일 이름과 관련된 다양한 호출이 뒤따릅니다. 이는 거의 확실히 그렇습니다)과 대부분의 프로그램에서 실행되는 호출입니다. 및 ...을 ld.so
포함하여 C 라이브러리 함수가 작동하도록 만든 다음 결국에는 읽게 됩니다.mmap
brk
표준 입력:
read(0,
이것은 구문입니다 strace
. 프로세스 cat
는 다음과 같습니다.아니요말 그대로 매개변수를 전달하는 과정에서 read
(구문은 이전에 사용하지 않은 C 프로그래머와 유사해 보일 수 있으므로 strace
). 대신 read
시스템 호출을 수행합니다.아직 반환되지 않았습니다.. 데이터를 읽었거나 입력 끝에 도달하면 반환됩니다.
예를 들어 를 입력한 foo
다음 을 누르 십시오 Enter. 그러면 다음과 같은 내용이 표시됩니다.
"foo\n", 131072) = 4
write(1, "foo\n", 4foo
) = 4
read(0,
그게 무슨 뜻이야? 종료하고 cat
( Ctrl줄 시작 부분에 + 추가 또는 아무 곳에나 + 추가) 리디렉션하여 출력을 억제하면서 다시 실행하면 더 쉽게 볼 수 있습니다.DCtrlC/dev/null
strace cat >/dev/null
strace
작성된 대로 출력을 볼 수 있습니다.표준 에러그리고 넌 리디렉션만 했어표준 출력. 그러나 이제 cat
자체 출력 foo
과 사용자가 제공한 개행 문자는 표시되지 않습니다. 입력 하고 누른 foo
후에 표시되는 내용은 Enter다음과 같습니다 .
"foo\n", 131072) = 4
write(1, "foo\n", 4) = 4
read(0,
즉, read
호출이 완료되고 읽기 foo
뒤에 로 표시되는 개행 문자가 옵니다 \n
. cat
그런 다음 호출은 write
동일한 문자열을 출력에 씁니다. C 코드에는 호출이 없을 수도 있습니다 cat
. write
대신 C 라이브러리 함수(예: fprintf
또는 ) 를 사용하여 쓰기를 수행할 수 있습니다 . 이는 시스템 호출이 아니고 궁극적으로 시스템 호출을 사용하여 작동하기 때문에 fputs
출력에 표시되지 않습니다 . 가 전달 되어 커널에 4바이트를 써야 한다고 알려줍니다 .strace
write
4
write
f
o
o
\n
입력을 계속 읽으려면 this 를 호출 write
한 후 다시 cat
호출하십시오 . read
계속해서 입력을 주고 call 을 확인한 write
다음 read
다시 호출할 수 있습니다. 예를 들어 다음을 입력 abracadabra
하고 누릅니다 Enter.
"abracadabra\n", 131072) = 12
write(1, "abracadabra\n", 12) = 12
read(0,
완료되면 마지막 항목을 입력한 후 Enter(또는 + )를 누른 다음 Ctrl+ 를 누르세요. 입력을 마치면 종료되고 다음이 표시됩니다.DCtrlDcat
strace
read(0, "", 131072) = 0
munmap(0x7f856a591000, 139264) = 0
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++