명명 된 파이프, 파일 설명자 및 EOF 인쇄하고 쉘은 죽습니다. 왜? 다음 실험

bash 프롬프트가있는 동일한 사용자의 두 창 창 1에서 다음을 입력하십시오.

$ mkfifo f; exec <f

따라서 bash는 이제 파일 디스크립터 0에서 이름을 가진 pipe에 맵핑하려고합니다 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 > f에서 window-1 쉘을 닫지 않습니다.

대답은 명명 된 파이프를 참조하는 창 2의 파일 설명자 3 의 존재 와 관련이 있어야합니까 ?!



답변

그것은 함께 할 수있다 닫는 파일 기술자의.

첫 번째 예제에서는 echo을 연결하기 위해 셸이 여는 표준 출력 스트림에 씁니다. f종료되면 셸에서 디스크립터가 닫힙니다. 수신 측에서 표준 입력 스트림 (에 연결된 f) 에서 입력을 읽는 쉘은 표준 입력 의 파일 끝 조건으로 인해 ls실행 된 ls다음 종료됩니다.

파일 끝 조건은 명명 된 파이프 (이 예제에서는 오직 하나)에 대한 모든 작성자가 파이프의 끝을 닫았 기 때문에 발생합니다.

두 번째 예에서는 exec 3>f에 쓰기 위해 파일 설명자 3을 연 f다음 echo씁니다 ls. echo명령이 아닌 파일 디스크립터가 열린 쉘입니다 . 디스크립터는 사용자가 할 때까지 열려 있습니다 exec 3>&-. 수신 측에서 표준 입력 스트림 (에 연결된 f) 에서 입력을 읽는 쉘 은 read ls를 실행 ls한 다음 더 많은 입력을 기다립니다 (스트림이 여전히 열려 있기 때문에).

스트림에 대한 모든 작성자 (쉘, via exec 3>fecho)가 파이프의 끝을 닫지 않았 으므로 스트림은 열린 상태로 유지됩니다 ( exec 3>f아직 유효).


나는 echo그것이 외부 명령 인 것처럼 위에서 언급했습니다. 쉘에 내장되었을 가능성이 높습니다. 그럼에도 불구하고 효과는 같습니다.


답변

그다지 많지 않습니다. 파이프에 작가가 없을 때 독자에게 가까워 보입니다. 즉 읽을 때 EOF를 반환하고 열 때 차단합니다.

Linux 매뉴얼 페이지에서 ( pipe(7)참조 fifo(7)) :

파이프의 쓰기 끝을 참조하는 모든 파일 디스크립터가 닫히면 read(2)파이프에서 시도하면 파일 끝이 표시됩니다 ( read(2)0이 리턴 됨).

쓰기 끝을 닫는 것은의 끝에서 내재적으로 발생 echo ls >f하는 것이며 다른 경우 파일 설명자는 열린 상태로 유지됩니다.


답변

@ Kusalananda와 @ikkachu의 두 가지 대답을 읽은 후에 이해합니다. window-1에서 쉘은 파이프의 쓰기 끝을 열고 닫을 무언가를 기다리고 있습니다. 쓰기 끝이 열리면 window-1의 쉘이 프롬프트를 인쇄합니다. 쓰기 끝이 닫히면 쉘은 EOF를 받고 죽습니다.

첫 번째 상황에 : 윈도우-2면에서 우리는 두 가지 상황이 내 질문에 설명이 echo ls > f거기에 우리가있다, 그래서 어떤 파일 기술자 (3), 없다, echo그 산란과 stdinstdout모양이 같은 :

0 --> tty
1 --> f

그런 다음 echo종료하고 셸은 두 설명자를 모두 닫습니다. 파일 디스크립터 1이 닫히고 참조되기 때문에 f쓰기 끝 f이 닫히고 EOF가 window-1이됩니다.

두 번째 상황에서는 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

그런 다음 쉘은를 포함하여 위의 세 가지 설명자를 닫지 ff여전히 쉘 자체에서 이에 대한 참조를 갖습니다. 이것이 중요한 차이점입니다. exec 3>&-@Kusalananda가 지적한 것처럼 설명자 3을 닫으면 마지막으로 열린 참조가 닫히고 EOF가 window-1이됩니다.