명명된 파이프, 파일 설명자 및 EOF

명명된 파이프, 파일 설명자 및 EOF

bash 프롬프트가 있는 두 개의 창, 동일한 사용자. 창-1에 입력:

$ mkfifo f; exec <f

따라서 bash는 이제 명명된 파이프에 매핑되는 파일 설명자 0에서 읽으려고 시도합니다 f. 창 2에 다음을 입력합니다.

$ echo ls > f

이제 window-1이 ls를 인쇄하고 쉘이 종료됩니다. 왜?

다음 실험: 를 사용하여 window-1을 다시 엽니다 exec <f. 창 2에 다음을 입력합니다.

$ exec 3>f
$ echo ls >&3

위의 첫 번째 줄 다음에 window-1이 깨어나서 프롬프트를 인쇄합니다. 왜? 위의 두 번째 줄 이후 window-1은 ls출력을 인쇄하고 셸은 활성 상태로 유지됩니다. 왜? 실제로 이제 window-2에서는 echo ls > fwindow-1 셸이 닫히지 않습니다.

대답은 다음과 같아야합니다존재하다window-2의 파일 설명자 3은 명명된 파이프를 참조합니까? !

답변1

이는 다음과 관련이 있습니다.폐쇄파일 설명자.

첫 번째 예에서 echo표준 출력 스트림에 쓰는 경우 쉘은 에 연결하기 위해 스트림을 열고 f종료되면 해당 설명자가 쉘에 의해 닫힙니다. 수신측에서는 표준 입력 스트림( 에 연결된)에서 f입력을 읽는 쉘이 을 읽고 ls실행한 ls다음 표준 입력의 파일 끝 조건으로 인해 종료됩니다.

파일 끝 조건은 명명된 파이프의 모든 기록기(이 예에서는 하나만)가 해당 파이프의 끝을 닫았기 때문에 발생합니다.

두 번째 예에서는 파일 설명자 3이 쓰기용으로 열린 다음 쓰기 위해 exec 3>f열립니다 . 이제 명령이 아닌 파일 설명자를 여는 쉘입니다 . 설명자는 이 작업을 수행할 때까지 열린 상태로 유지됩니다 . 수신측에서는 표준 입력 스트림(에 연결된)에서 입력을 읽는 셸이 읽고 실행 한 다음 추가 입력을 기다립니다(스트림이 여전히 열려 있기 때문).fecholsechoexec 3>&-flsls

모든 작성자(셸, via exec 3>fecho아니요파이프 끝을 닫았습니다( exec 3>f아직 유효함).


echo위의 내용을 마치 외부 명령인 것처럼 작성했습니다 . 케이스에 내장되어 있을 가능성이 높습니다. 그래도 효과는 동일합니다.

답변2

별로: 파이프에 작성자가 없으면 독자에게는 닫힌 것처럼 보입니다. 즉, 읽을 때 EOF를 반환하고 열 때 차단됩니다.

Linux 매뉴얼 페이지(pipe(7), 하지만 다음도 참조하세요.fifo(7)):

파이프의 쓰기 끝을 참조하는 모든 파일 설명자가 닫힌 경우 read(2)파이프에서 읽으려고 하면 파일 끝이 표시됩니다( read(2)0이 반환됨).

쓰기 쪽을 닫는 것은 당신이 말했듯이 파일 설명자의 끝에서 암시적으로 발생하며 echo ls >f, 다른 경우에는 파일 설명자가 열린 상태로 유지됩니다.

답변3

@Kusalananda와 @ikkachu의 답변을 모두 읽은 후 이해가 된 것 같습니다. window-1에서 쉘은 파이프의 쓰기 측을 열고 닫을 무언가를 기다리고 있습니다. 쓰기 쪽이 열리면 window-1의 셸이 프롬프트를 인쇄합니다. 쓰기 측이 닫히면 쉘은 EOF를 수신하고 종료됩니다.

window-2 측에는 내 질문에 설명된 두 가지 사례가 있습니다. 첫 번째 경우에는 echo ls > f파일 설명자 3이 없으므로 echo이를 생성 stdin하고 그 stdout합계는 다음과 같습니다.

0 --> tty
1 --> f

그런 다음 echo종료되고 쉘은 두 설명자를 모두 닫습니다. 파일 설명자 1이 닫히고 참조되기 때문에 f쓰기 끝이 f닫히고 이로 인해 window-1에 대한 EOF가 발생합니다.

두 번째 경우에는 exec 3>f쉘이 다음 환경을 채택하도록 쉘에서 실행합니다.

bash:
0 --> tty
1 --> tty
2 --> tty
3 --> f

이제 를 실행하면 echo ls >& 3쉘은 다음과 같이 파일 설명자를 할당합니다 echo.

echo:
0 --> tty
1 --> f     # because 3 points to f
2 --> tty

그런 다음 셸은 위의 세 설명자( 를 포함)를 닫지만 f여전히 f셸 자체에서 해당 설명자를 참조합니다. 이것은 중요한 차이점입니다. 설명자 3을 닫으면 exec 3>&-마지막 열린 참조가 닫히고 @Kusalananda가 지적한 대로 EOF가 window-1로 이동하게 됩니다.

관련 정보