vfork 또는 포크의 하위 프로세스가 왜 종료() 대신 _exit()를 호출해야 합니까?

vfork 또는 포크의 하위 프로세스가 왜 종료() 대신 _exit()를 호출해야 합니까?

매뉴얼 페이지에서 vfork():

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

_exit()왜 아이들은 단순히 call 대신 an을 사용해야 합니까 exit()? 이 기능이 vfork()및 에서 작동하기를 바랍니다 fork().

답변1

~처럼일찍 만났어요, vfork하위 프로세스가 상위 프로세스의 메모리에 액세스하는 것을 허용하지 않습니다.exitC 라이브러리 함수입니다(그래서자주 쓴다처럼 exit(3)). C 스트림 플러시 및 닫기( 에 선언된 함수를 통해 파일 열기 stdio.h), 에 등록된 사용자 지정 함수 실행 등 다양한 정리 작업을 수행합니다 atexit. 이러한 모든 작업에는 프로세스 메모리에 대한 읽기 및 쓰기가 포함됩니다.

_exit정리하지 않고 종료합니다. 이는 직접적인 시스템 호출(그래서 작성되었습니다 _exit(2))이며 일반적으로 시스템 호출 번호를 프로세서 레지스터에 넣고 특정 프로세서 명령을 실행(시스템 호출 처리기로 분기)하여 구현됩니다. 이는 프로세스 메모리에 접근할 필요가 없으므로 나중에 실행해도 안전합니다 vfork.

이후에는 fork그러한 제한이 없습니다. 이제 상위 및 하위 프로세스가 완전히 자율적입니다.

답변2

exit등록된 함수를 호출하여 atexit복사된 부품 외부의 데이터에 액세스하는 등 추가 정리를 수행합니다. _exit시스템 호출은 정리 없이 직접 실행됩니다(커널 내 제외).

답변3

하위 프로세스가 종료될 때 stdio(또는 기타) 버퍼를 플러시하는 것을 방지하기 위해 하위 프로세스 호출 _exit()가 있습니다. 하위 프로세스는 상위 프로세스의 정확한 복사본을 구성하므로 하위 프로세스는 여전히 상위 프로세스가 "stdout" 또는 "stderr"에 가지고 있던 모든 것, 즉 <stdio.h>의 버퍼를 갖습니다. 자식 프로세스의 atexit 처리기에서 하나, 부모 프로세스에서 하나(부모 프로세스의 버퍼가 가득 차서 플러시된 경우)를 호출하여 이중 출력을 얻을 수 있습니다(부적절한 경우).

위의 답변은 stdio.h의 세부 사항에 초점을 맞추고 있지만 위의 답변 중 하나에서 알 수 있듯이 아이디어는 다른 버퍼링된 I/O에도 적용될 수 있습니다.

답변4

exit():- i/o 스트림 닫기 등과 같은 일부 정리 작업을 수행한 다음 커널로 돌아갑니다. _exit():- 정리 작업을 수행하지 않고 커널로 직접 이동합니다.

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

vfork(): 상위 프로세스와 하위 프로세스는 동일한 파일 테이블을 사용하므로 하위 프로세스의 변경 사항은 상위 프로세스의 환경 매개변수에 영향을 줍니다. 예를 들어, 이제 하위 프로세스에 의해 변수가 var=10실행되고 상위 프로세스가 실행되는 경우 상위 프로세스의 출력에서도 그 효과를 볼 수 있습니다 var++.var++

내가 말했듯이 exit()in을 사용하면 vfork()모든 I/O가 이미 닫혀 있습니다. 따라서 상위 프로세스가 올바르게 실행되더라도 모든 변수가 플러시되고 모든 스트림이 닫히기 때문에 올바른 출력을 얻을 수 없습니다.

관련 정보