vfork 또는 포크의 자식이 exit () 대신 _exit ()를 호출해야하는 이유는 무엇입니까?


12

의 맨 페이지에서 vfork():

vfork ()는 자식이 execve (2) 또는 _exit (2)를 호출 할 때까지 부모가 일시 중지된다는 점에서 fork ()와 다릅니다. 자식은 execve ()가 자식에 의해 발행 될 때까지 스택을 포함하여 부모와 모든 메모리를 공유합니다. 자식은 현재 함수에서 리턴하거나 exit ()를 호출해서는 안되지만 _exit ()를 호출 할 수 있습니다.

왜 아이 _exit()는 단순히 전화하기보다는 오히려 전화를 사용해야 exit()합니까? 이것이 vfork()와 에 모두 적용되기를 바랍니다 fork().


2
당신은 이전에 관심이 있다면 유닉스 C API 호출의 ontopic 네스 토론
xenoterracide

답변:


11

으로 이전에 볼 , vfork자식 프로세스는 부모의 메모리에 액세스 할 수 없습니다. exitC 라이브러리 함수입니다 (그래서 종종로 작성 되는 이유 exit(3)). C 스트림 플러시 및 닫기 (에 선언 된 함수를 통해 파일이 열림 stdio.h) 및에 등록 된 사용자 지정 함수 실행 과 같은 다양한 정리 작업을 수행합니다 atexit. 이러한 모든 작업에는 프로세스 메모리를 읽고 쓰는 작업이 포함됩니다.

_exit정리하지 않고 종료합니다. 직접 시스템 호출 (이로 작성된 이유 _exit(2))이며 일반적으로 시스템 호출 번호를 프로세서 레지스터에 배치하고 특정 프로세서 명령어 (시스템 호출 핸들러로 분기)를 실행하여 구현됩니다. 프로세스 메모리에 액세스 할 필요가 없으므로 이후에 수행해도 안전합니다 vfork.

이후 fork에는 그러한 제한이 없습니다 : 부모와 자식 프로세스는 이제 완전히 자율적입니다.


vfork는 자식 프로세스가 부모의 메모리에 접근하는 것을 허용하지 않습니까? 그러나 나는 그들이 같은 주소 공간을 공유한다고 생각했기 때문에 아이는 부모의 주소 공간에 액세스 할 수 있습니다. 이해가 잘못 되었습니까?
Sen

포크 후에는 그러한 제한이 없습니다 : 부모와 자식 프로세스는 이제 완전히 자율적입니다. 그것은 포크의 자식에서 exit () 를 호출 할 수 있다는 것을 의미합니까 ?
Sen

1
@Sen : 자녀는 부모의 기억에 접근 할 수 없습니다. 시도하면 커널이 보호하지 않기 때문에 작동 할 수 있습니다. 그러나 그 효과는 의도 한 것이 아닐 수도 있습니다. 예를 들어, 컴파일러가 레지스터에 값을 남겨두기로 결정하면 상위 프로세스에서 볼 수 없습니다.
Gilles 'SO- 악의를 멈춰라'

@ 센 : 포크 후, 당신은 호출 종료 또는 다른 기능을 수행 할 수 있습니다. 모든 프로세스는 포크 후에 시작합니다 (Linux에서는 초기 프로세스조차도 init커널에 의해 포크됩니다).
Gilles 'SO- 악마 그만해'

3

exitatexit복사 된 부품 외부의 데이터에 액세스 하여 등록 된 함수 호출과 같은 추가 정리를 수행 합니다. _exit커널 내를 제외한 모든 정리없이 직접 syscall을 수행합니다.


... fork ()는 모든 것을 복사하므로 exit ()를 호출 할 수 있으며 현재 함수에서 확실히 반환 할 수 있습니다.
derobert

3

자식 프로세스가 종료 될 때 stdio (또는 다른) 버퍼를 비우지 않도록 자식 호출 _exit ()가 있습니다. 자식 프로세스는 부모 프로세스의 정확한 복사본을 구성하기 때문에 자식 프로세스는 여전히 부모가 "stdout"또는 "stderr"에있는 <stdio.h>의 버퍼를 가지고 있습니다. 부모 프로세스의 버퍼가 가득 차고 플러시되면 exit ()를 호출하여 자식 프로세스의 atexit 핸들러에서 하나, 부모에서 하나를 호출하여 이중 출력을 얻을 수 있습니다.

위의 답변이 stdio.h 특정 사항에 집중한다는 것을 알고 있지만 위의 답변 중 하나가 나타내는 것처럼 다른 아이디어는 아마도 버퍼링 된 다른 I / O로 넘어갑니다.


1

exit():-i / o 스트림을 닫는 것과 같은 많은 정리 작업을 수행 한 다음 커널로 돌아갑니다. _exit():-커널에 직접옵니다 (정리 작업을 수행하지 마십시오).

fork() : 부모와 자식 모두 파일 테이블이 다르므로 자식에 의한 변경은 부모의 환경 매개 변수에 영향을 미치지 않으며 그 반대도 마찬가지입니다.

vfork(): 부모와 자식 모두 동일한 파일 테이블을 사용하므로 자식에 의한 변경은 부모의 환경 매개 변수에 영향을줍니다. 예를 들어 일부 변수 var=10는 이제 var++자식에 의해 실행 되고 부모를 실행하면 부모 var++의 출력에서도 영향을 볼 수 있습니다.

난 당신이 사용하는 경우 말했듯 exit()vfork()다음의 모든 I / O가 이미 닫혀 있습니다. 따라서 부모가 올바르게 실행 되더라도 모든 변수가 플러시되고 모든 스트림이 닫히므로 올바른 출력을 얻을 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.