fork ()가 파일 디스크립터를 리턴하도록 설계된 이유는 무엇입니까?


16

자신에 대한 웹 페이지 자기 파이프 트릭 , 댄 번스타인은 경쟁과 조건에 대해 설명 select()하고 신호를 제공하는 해결 방법을하고 있다는 결론

물론 올바른 것은 fork()프로세스 ID가 아닌 파일 설명자를 반환하는 것입니다 .

그는 이것이 의미하는 바는- select()상태 변경에 대한 알림을 받기 위해 신호 처리기를 사용하지 않고 자식 프로세스에서 상태 변경을 처리 할 수 있다는 것 입니까?


해당 기사에 입력과 출력이 섞여 있거나 올바르게 읽지 않습니까?
ctrl-alt-delor

파이프를 통해 신호를 전달하도록 요청할 수 있습니다. 그게 내가하는 일입니다.
ctrl-alt-delor

@ ctrl-alt-delor, 그렇습니다. 그는 "파이프 입력 / 출력"을 조금 이상하게 사용하는 것 같습니다. 그 텍스트는 2003 년에 왔으며, 잘 모르겠습니다 signalfd.
ilkkachu

5
Dan은 의도적으로 조금 도발적 일 수 있지만 자신이 말하는 내용을 알고 있습니다. 내가 의도적으로 도발적 이었다면 당연히 SIGCHLD를 제거하는 것이 옳다고 생각합니다.
Steve Summit

1
@mosvy 나는 약간 과장하고 있지만, SIGCHLD를 사용하려고 시도한 사람을 본 모든 프로그램과 모든 프로그래머는 그것에 문제가 있었다. 경쟁 조건이 일어나기를 기다리고 있습니다. 우리가 모두 막고 있었을 때 wait(), 당신이 할 수 없었던 일들이 있었으므로 누군가가 SIGCHLD를 발명했지만 나쁜 일이었습니다. 내 경험에 의하면, 지금 그들이 존재, 블로킹, 좋은 뿌리 wait3(), wait4()및 / 또는 waitpid()주요 장소에서 통화 (아마도 메인 이벤트 루프)는 훨씬 뛰어난 대안이다.
Steve Summit

답변:


14

문제는 소스에 설명되어 있으며 select()와 같은 신호로 중단되어야 SIGCHLD하지만 경우에 따라 제대로 작동하지 않습니다. 따라서 해결 방법은 파이프에 신호 쓰기를하는 것 select()입니다. 파일 디스크립터를 보는 select()것이 문제이므로 문제를 해결할 수 있습니다.

이 해결 방법은 기본적으로 신호 이벤트를 파일 디스크립터 이벤트로 바꿉니다. 경우 fork()단지 첫 번째 장소에서 FD를 반환하는 FD가 다음 아마도 직접 사용될 수로, 해결 방법은 필요하지 않을 것입니다 select().

예, 마지막 단락의 설명은 나에게 맞는 것 같습니다.


fd (또는 다른 종류의 커널 핸들)가 일반 프로세스 ID 번호보다 나은 또 다른 이유는 프로세스가 종료 된 후 PID가 재사용 될 수 있기 때문입니다. 프로세스에 신호를 보낼 때 문제가 될 수 있습니다. 프로세스가 자신이 생각하는 프로세스인지, 동일한 PID를 재사용하는 프로세스가 아닌지 확실하지 않을 수 있습니다. ( wait()PID를 해제 하려면 부모가 자식 을 실행해야하기 때문에 자식 프로세스에 신호를 보낼 때 이것이 문제가되지 않는다고 생각합니다 .)


즉, PID 재사용이 문제가되는 것에 대해 읽은 사례를 정확하게 기억하지 못하므로 누군가가 그것을 자세히 설명하거나 위의 내용을 편집 하거나 위의 내용을 편집 하고 싶다면 언제든지 그렇게하십시오.
ilkkachu

2
이미 언급했듯이 부모가 자신의 자식 pid가 재사용되었음을 알게 된 변명은 없습니다. 그것은 전화하는 사람이기 때문에 그러한 상황을 완전히 통제 할 수 있습니다 wait().
여호수아

이러한 프로세스를 좀비 프로세스 라고 합니다 . "실행이 완료되었지만 프로세스 테이블에 여전히 항목이있는 프로세스 :"종료 상태 "의 프로세스입니다. 이는 하위 프로세스에서 발생합니다.이 프로세스는 여전히 상위 항목을 허용해야합니다. 자녀의
퇴사

6
리눅스 에서 파일 디스크립터 (pidfd)를 리턴 할 수 있다는 것을 언급 할 가치가있다. 이것은 clone포크가 LInux에서 호출하는 실제 시스템 호출이다. 이를 가능하게하는 플래그를 호출 CLONE_PIDFD합니다 (예 : lwn.net/Articles/784831 참조) .
KJ Tsanaktsidis

1
@Lie Ryan, Re " fork ()는 로컬 핸들이 아닌 전역 핸들을 반환하는 것이 개념적으로 더 정확 합니다. Windows는 프로세스 핸들을 사용 하기 때문 입니다. pid 및 종료 코드는 프로세스에 대한 모든 핸들이 닫힐 때까지 (부모의 응답을 기다리지 않고) 유닉스 시스템에서 일반적인 경쟁 조건을 피합니다. 핸들이 프로세스를 활성 상태로 유지하면 전역 핸들이 아닌 로컬 핸들이되는 것이 훨씬 합리적입니다.
ikegami

9

"유닉스와 다른 방식으로 디자인하면 좋을 것"이라고 생각합니다.

PID의 문제점은 다른 프로세스에 재사용 할 수있는 글로벌 네임 스페이스에 있으며, fork()항상 자식 프로세스를 참조하도록 보장되는 어떤 종류의 핸들을 부모에 반환 하면 좋을 것입니다. 상속 또는 유닉스 소켓 / SCM_RIGHTS[1]을 통해 다른 프로세스로 전달할 수 있습니다.

PID 대신 pid-fd를 리턴하는 플래그를 추가하는 것을 포함하여 Linux에서이를 수정하기위한 최근의 노력에 대해서는 여기 에서 논의를 참조하십시오 clone().

그러나 부모 프로세스에 자식의 상태를 알리는 신호가 메인 루프에서 처리하려는 유일한 신호가 아니기 때문에 자체 파이프 해킹 [2] 또는 더 나은 인터페이스가 필요하지 않습니다. 프로그램의. 불행히도 epoll(7) + signalfd(2)Linux 또는 kqueue(2)BSD 와 같은 것은 표준이 아니며, 유일한 표준 인터페이스 (이전 시스템에서는 지원되지 않음)가 훨씬 열등 pselect(2)합니다.

[1] waitpid()syscall이 리턴되고 리턴 값이 사용 된 시간까지 PID가 재순환되는 것을 막는 것은 아마도 새로운 시스템에서 waitid(.., WNOWAIT)대신 에 사용함으로써 달성 될 수 있습니다 .

[2] 나는 그가 그것을 발명했다고 DJ 번스타인의 주장에 대해서는 언급하지 않을 것이다.


8

Bernstein은이 "Right Thing"설명에 대해 많은 맥락을 제시하지는 않지만 추측 할 수 있습니다. fork (2)가 PID를 반환하면 open (2), creat (2) 등이 파일 설명자를 반환하는 것과 일치하지 않습니다. 나머지 유닉스 시스템은 PID 대신 프로세스를 나타내는 파일 디스크립터를 사용하여 프로세스 조작을 수행했을 수 있습니다. 시스템 호출 signalfd (2) 가 존재하는데, 이는 신호와 파일 디스크립터 사이에서 다소 더 나은 상호 작용을 허용하며 프로세스를 나타내는 파일 디스크립터가 작동 할 수 있음을 보여줍니다.


signalfd (2)는 정말 훌륭합니다. Linux 전용이기 때문에 너무 나쁩니다.
Lassi

1
pidfd_open리눅스에서도 토론이있었습니다. 예를 들어 lwn.net/Articles/789023
dhag
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.