하위 프로세스가 파이프를 열어두나요?

하위 프로세스가 파이프를 열어두나요?

파이프에서 실행될 때 하위 프로세스를 시작하는 프로그램의 동작을 이해하려고 합니다.

이 bash 프로그램 fork.sh는 즉시 다음을 인쇄하고 반환합니다.

(sleep 1) &
echo 'here'

하지만 파이프에 연결하면 읽기 측이 수면이 완료될 때까지 기다리는 것처럼 보입니다.

$ time bash fork.sh | wc
       1       1       5

real    0m1.014s

나는 또한 이것을 Ruby에서 시도했고 수면 차단을 방지하기 위해 몇 가지 추가 호출을 수행했습니다.

Process.detach(fork { sleep 1 })
puts 'here'
fork {
  sleep 1
  Process.daemon
}
puts 'here'

하지만 그들의 행동은 똑같습니다.

이 문제(Unix, 파일 설명자 등의 측면에서)의 원인이 무엇인지, 그리고 파이프가 1초 내에 반환되도록 이들 중 하나를 재정의할 수 있는 방법이 있는지 알고 싶습니다.


편집: 아래 답변은 Ruby 예제의 문제점을 파악하는 데 도움이 되었습니다. 호출이 daemon()먼저 이루어져야 합니다. 나는 그것이 어떤 방식으로든 전체 과정에 적용된다고 생각했을 것이다.

답변1

  1. 하위 프로세스는 상위 프로세스로부터 모든 파일 설명자를 상속받습니다.
  2. 명령을 실행할 때( sleep여기서는 쉘에 내장 명령이 없다고 가정)실행 시 닫기플래그는 꺼져 있지만 쉘은 이를 stdout(fd 1)에 설정하지 않습니다.
  3. 관로리더다음과 같은 경우에만 EOF를 얻을 수 있습니다.모두쓰기 끝을 가리키는 파일 설명자가 닫혔습니다.
time bash fork.sh | wc

sleep프로세스가 시작부터 읽고 있는 파이프의 쓰기 끝을 fork.sh가리키는 표준 출력을 삭제 하도록 해야 합니다 .wcfork.sh

(sleep 1 >/dev/null) &
echo 'here'

이 경우 sleep .. >&-(다른 곳으로 리디렉션하지 않고 stdout을 닫는 것)도 작동하지만 프로세스가 일부 파일을 열면 반환된 파일 설명자가 1 = std 출력이 되어 가정을 깨뜨릴 수 있으므로 일반적으로 권장하지 않습니다. 오류를 유발합니다.

관련 정보