파이프를 사용하여 서브쉘 및 stdout의 동작 이해

파이프를 사용하여 서브쉘 및 stdout의 동작 이해

.cstdin에서 일부 입력을 받은 다음 다음과 같이 해당 실행 파일에 입력을 제공하는 파일과 해당 실행 파일(foo라고 가정)이 있다고 가정해 보겠습니다 /bin/sh.

python -c "<some script to feed input>" | ./foo

나는 foo가 호출한 쉘이 즉시 닫히고 foo가 종료되는 것을 관찰했습니다. 그러나 IRC의 누군가가 다음과 같이 제안했습니다.

(python -c "<some script to feed input>"; cat) | ./foo

호출된 서브셸을 ./foo계속 실행 상태로 유지하세요. 여기서 무슨 일이 일어나고 있는지 궁금합니다.

내 추측: 첫 번째 경우, Python 스크립트의 stdout이 완료되자마자 닫혀서 ./foo종료 프로세스의 stdin 에 EOF를 보내는가 ./foo? 그러나 시스템 호출은 차단 호출로 간주되어 ./foo종료되지 않기 때문에 이것은 나에게 이해가 되지 않습니다. 오해를 바로잡을 수 있는 도움과 리소스에 대한 조언을 듣고 싶습니다. 감사해요!

답변1

"EOF 보내기"와 같은 것은 없습니다. 더 이상 읽을 데이터가 없으면 파일 끝에 도달합니다.

첫 번째 코드 조각에서 Python 스크립트가 종료되면 더 이상 쓰기 위해 파이프가 열려 있는 프로세스가 없습니다. 따라서 foo파이프로 전송된 모든 데이터를 읽고 나면 표준 입력에서 파일 끝 조건을 감지합니다.

두 번째 코드 조각에서 Python 스크립트가 종료되면 파이프는 여전히 하위 셸에 의해 열려 있습니다. 따라서 fooPython 스크립트에서 생성된 모든 데이터를 읽은 후에도 계속해서 추가 입력을 기다립니다. cat자체 표준 입력에서 데이터를 읽고 전달하는 하위 쉘이 시작됩니다 . 종료 하면 cat상황은 이전과 동일합니다. 어떤 프로세스도 더 이상 쓰기 위해 파이프를 열지 않으며 foo입력 끝에 도달합니다.

프로세스가 read시스템 호출 내에서 차단되면 시스템 호출이 반환될 수 있는 몇 가지 이유가 있습니다.

  • 데이터를 사용할 수 있는 경우 read양수 값이 반환되고 해당 데이터에 전달된 버퍼에 해당 바이트가 저장됩니다.
  • 파일의 끝에 도달하면 read0이 반환됩니다. 일반 파일의 경우 파일 위치가 파일 끝에 도달하면 이런 일이 발생합니다. 파이프의 경우 이는 파일을 연 마지막 프로세스가 종료되고 파이프의 버퍼가 완전히 소모될 때 발생합니다.
  • 오류가 발생하면 read-1이 반환됩니다.

관련 정보