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 > f
window-1 셸이 닫히지 않습니다.
대답은 다음과 같아야합니다존재하다window-2의 파일 설명자 3은 명명된 파이프를 참조합니까? !
답변1
이는 다음과 관련이 있습니다.폐쇄파일 설명자.
첫 번째 예에서 echo
표준 출력 스트림에 쓰는 경우 쉘은 에 연결하기 위해 스트림을 열고 f
종료되면 해당 설명자가 쉘에 의해 닫힙니다. 수신측에서는 표준 입력 스트림( 에 연결된)에서 f
입력을 읽는 쉘이 을 읽고 ls
실행한 ls
다음 표준 입력의 파일 끝 조건으로 인해 종료됩니다.
파일 끝 조건은 명명된 파이프의 모든 기록기(이 예에서는 하나만)가 해당 파이프의 끝을 닫았기 때문에 발생합니다.
두 번째 예에서는 파일 설명자 3이 쓰기용으로 열린 다음 쓰기 위해 exec 3>f
열립니다 . 이제 명령이 아닌 파일 설명자를 여는 쉘입니다 . 설명자는 이 작업을 수행할 때까지 열린 상태로 유지됩니다 . 수신측에서는 표준 입력 스트림(에 연결된)에서 입력을 읽는 셸이 읽고 실행 한 다음 추가 입력을 기다립니다(스트림이 여전히 열려 있기 때문).f
echo
ls
echo
exec 3>&-
f
ls
ls
모든 작성자(셸, via exec 3>f
및echo
아니요파이프 끝을 닫았습니다( exec 3>f
아직 유효함).
echo
위의 내용을 마치 외부 명령인 것처럼 작성했습니다 . 케이스에 내장되어 있을 가능성이 높습니다. 그래도 효과는 동일합니다.
답변2
답변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로 이동하게 됩니다.