포트를 읽는 동안 고양이는 어떻게 일시 중지합니까?

포트를 읽는 동안 고양이는 어떻게 일시 중지합니까?

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실제로프로세스를 일시 중지한 다음 실행하여 psPID를 찾은 다음 를 실행하여 다시 시작합니다 fg. 또는 tty첫 번째 터미널에서 실행하여 터미널 장치의 경로 이름을 표시합니다. GNU/Linux에서는 다음과 같을 수 있습니다. /dev/tty2또는 /dev/pts/4--then run cat, 두 번째 터미널에서 실행, 교체ps -t ttyttytty첫 번째 터미널의 출력입니다.

두 번째 터미널에서 교체한 곳을 실행하세요.ps pidpidcat 프로세스의 실제 프로세스 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 pidkill -9 pid

추적 프로세스

gdb일반적으로 프로그램을 디버그하려면 또는 와 같은 디버거에서 프로그램을 엽니다 lldb. 그러나 GNU/Linux를 포함한 일부 시스템에는 strace다음 과 같은 프로그램이 있습니다.시스템 호출프로세스가 진행되고 있습니다. 터미널에서 입력을 기다리는 프로세스를 실행하는 데 를 사용하면 터미널의 프로세스에 더 많은 입력이 전송될 때까지 실행을 차단하는 strace각 호출을 볼 수 있습니다 . readFedora, CentOS, Debian 또는 Ubuntu와 같은 GNU/Linux 시스템이 있는 경우(이들은 예시일 뿐이고 다른 시스템도 많이 있음) 다음 명령을 실행해 보세요.

strace cat

일련의 시스템 호출을 볼 수 있습니다. 먼저 프로세스를 실행하는 호출( execve프로그램이 공유 라이브러리를 사용하는 경우 파일 이름과 관련된 다양한 호출이 뒤따릅니다. 이는 거의 확실히 그렇습니다)과 대부분의 프로그램에서 실행되는 호출입니다. 및 ...을 ld.so포함하여 C 라이브러리 함수가 작동하도록 만든 다음 결국에는 읽게 됩니다.mmapbrk표준 입력:

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바이트를 써야 한다고 알려줍니다 .stracewrite4writef 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+ 를 누르세요. 입력을 마치면 종료되고 다음이 표시됩니다.DCtrlDcatstrace

read(0, "", 131072)                     = 0
munmap(0x7f856a591000, 139264)          = 0
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

관련 정보