깨진 파이프로 유닉스 프로세스가 죽는 이유는 무엇입니까?


30

여기에 내가 생각한 몇 가지 옵션이 있습니다.

  1. 파이프에서 읽는 동안 I / O 오류가 발생했습니다.
  2. 파이프의 다른 쪽 끝에 쓰는 프로세스가 실패로 종료되었습니다.
  3. 파이프에 쓸 수있는 모든 프로세스가 파이프를 닫았습니다.
  4. 파이프의 쓰기 버퍼가 가득 찼습니다.
  5. 피어가 이중 파이프의 다른 방향을 닫았습니다.
  6. 파이프에서 읽을 수있는 프로세스가 없기 때문에 쓰기에 실패했습니다.
  7. 시스템 호출이 EPIPE 오류를 리턴했으며 오류 핸들러가 설치되지 않았습니다.

질문이 뭐야? 어느 것이 올바른지 묻고 있습니까, 아니면 파이프가 파손될 수있는 다른 것이 있습니까?
EightBitTony

@EightBitTony 다음 중 올바른 것
siamii

답변:


38

프로세스는 독자가없는 파이프 (명명 된) 또는 SOCK_STREAM 유형의 소켓에 쓰려고 시도 할 때 SIGPIPE를 수신합니다.

일반적으로 원하는 행동입니다. 일반적인 예는 다음과 같습니다.

find . | head -n 1

find일단 head종료 된 후에는 계속 실행 하고 싶지 않습니다 (그리고 해당 파이프에서 읽기 위해 열린 유일한 파일 설명자를 닫았습니다).

yes명령은 일반적으로 해당 신호를 사용하여 종료됩니다.

yes | some-command

일부 명령이 종료 될 때까지 "y"를 기록합니다.

명령이 종료 될 때뿐만 아니라 모든 독자가 파이프에 대한 읽기 fd를 닫았을 때입니다. 에서:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

서브 쉘이 명시 적으로 stdin을 닫은 후 파이프에서 1 (서브 쉘), 2 (서브 쉘 + 휴면), 1 (서브 쉘), 0 fd 판독 값이 표시되며 yesSIGPIPE를 수신하게됩니다.

위의 대부분의 쉘은 pipe(2)while을 ksh93사용 socketpair(2)하지만 동작은 동일합니다.

프로세스가 SIGPIPE를 무시하면 쓰기 시스템 호출 (일반적으로 ,, ... 일 write수 있음 )이 오류 와 함께 리턴됩니다 . 따라서 파손 된 파이프를 수동으로 처리하려는 프로세스는 일반적으로 SIGPIPE를 무시하고 EPIPE 오류에 대한 조치를 수행합니다.pwritesendspliceEPIPE


14

(6)

파이프에서 읽을 수있는 프로세스가 없기 때문에 쓰기에 실패했습니다.

디스크립터와 포크를 복제하지 않는 한, 시작해야 할 프로세스는 하나뿐입니다. 일반적으로 파이프에는 하나의 리더와 하나의 기록기가 있으며, 하나는 연결을 닫으면 파이프가 작동하지 않습니다. 명명 된 파이프를 사용하는 경우 여러 개의 연결을 직렬로 연결할 수 있지만 이러한 의미에서 각 파이프는 새 파이프를 나타냅니다. 따라서 스레드 또는 프로세스에 대한 "파이프"는 파일 디스크립터와 동의어입니다.

보낸 사람 man 7 pipe:

파이프의 읽기 끝을 참조하는 모든 파일 디스크립터가 닫히면 write (2)는 호출 프로세스에 대해 SIGPIPE 신호를 생성합니다. 호출 프로세스가이 신호를 무시하는 경우 오류 EPIPE와 함께 write (2)가 실패합니다.

따라서 "파손 된 파이프"는 EOF가 독자에게주는 것입니다.


0

끊어진 파이프는 쓰기 프로세스 전에 읽기 프로세스가 종료 될 때 발생합니다. 그래서 나는 함께 갈 것입니다 (6)


2
파이프에 읽거나 쓰는 여러 프로세스가있을 수 있으며 동일한 프로세스가 읽고 쓸 수 있습니다. 또한 종료하는 것이 아니라 파일 설명자를 닫는 것입니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.