자식 프로세스가 생성된 직후 exec() 또는 exit()를 호출할 때 vfork()를 사용하는 이유는 무엇입니까?

자식 프로세스가 생성된 직후 exec() 또는 exit()를 호출할 때 vfork()를 사용하는 이유는 무엇입니까?

운영 체제 개념 및 APUE 이론

vfork()를 사용하면 상위 프로세스가 일시 중지되고 하위 프로세스가 상위 프로세스의 주소 공간을 사용합니다. vfork()는 쓰기 시 복사를 사용하지 않기 때문에 자식 프로세스가 부모 프로세스의 주소 공간에 있는 페이지를 변경하는 경우 부모 프로세스가 다시 시작되면 변경된 페이지가 부모 프로세스에 표시됩니다. 그래서,vfork()는 하위 프로세스가 상위 프로세스의 주소 공간을 수정하지 않도록 주의해서 사용해야 합니다.

vfork()는 자식 프로세스가 생성된 직후 exec() 또는 exit()가 호출될 때 사용되도록 만들어졌습니다.

마지막 문장을 어떻게 이해해야 하나요?

vfork()호출을 통해 하위 프로세스가 생성되면 새 프로그램을 로드하여 상위 프로세스의 주소 공간이 수정되지 exec()않습니까 ?exec()

vfork()생성된 자식 프로세스를 호출하면 exit()자식 exit()프로세스가 종료되면 부모 프로세스의 주소 공간이 수정되지 않나요?

저는 개인적으로 리눅스를 선호합니다.

감사해요.

답변1

vfork()호출을 통해 하위 프로세스가 생성되면 새 프로그램을 로드하여 상위 프로세스의 주소 공간이 수정되지 exec()않습니까 ?exec()

아니요, exec()새 프로그램에는 새 주소 공간이 제공되며 상위 주소 공간은 수정되지 않습니다. 예시 보기execPOSIX의 기능에 대한 토론, 그리고리눅스 execve()맨페이지.

vfork()에 의해 생성된 하위 프로세스가 종료()를 호출하면 종료()는 하위 프로세스를 종료할 때 상위 프로세스의 주소 공간을 수정하지 않습니까?

간단 exit()합니다. 실행 중인 프로그램(라이브러리 포함)에 의해 설치된 종료 후크를 실행합니다. vfork()따라서 Linux에서는 더 제한적입니다.그것은 규정한다어떤 것의 목적을 가리킨다._exit()어느아니요C 라이브러리의 정리 기능을 호출합니다.

vfork()올바른 이해가 어려운 것으로 밝혀졌으며 현재 POSIX 표준 버전에서는 제거되었습니다.posix_spawn()사용되어야한다.

그러나 당신이 아니라면진짜당신이 무엇을 하고 있는지 알아야 합니다.아니요vfork()또는 posix_spawn();을 fork()사용 하세요 exec().

위에 링크된 Linux 맨페이지는 더 많은 컨텍스트를 제공합니다.

그러나 예전에는 fork(2) 호출자 데이터 공간의 완전한 복사본이 필요했는데, 이는 exec(3)일반적으로 an 직후에 수행되었기 때문에 종종 불필요했습니다. 따라서 효율성을 높이기 위해 BSD는 vfork() 상위 프로세스의 주소 공간을 완전히 복사하지 않고 호출이 발생하거나 종료될 때까지 상위 프로세스의 메모리 및 제어 스레드를 빌려오는 시스템 호출을 도입 했습니다 execve(2). 하위 프로세스가 해당 리소스를 사용하는 동안 상위 프로세스는 일시 중지됩니다. 의 사용은 vfork()까다롭습니다. 예를 들어 상위 프로세스에서 데이터를 수정하지 않는 것은 레지스터에 어떤 변수가 있는지 아는 것에 달려 있습니다.

답변2

을 호출하면 vfork()새 프로세스가 생성되고 새 프로세스는 상위 프로세스의 프로세스 이미지(스택 제외)를 차용합니다. 하위 프로세스에는 자체적으로 새로운 스택 별표가 부여되지만 return호출된 function 에서 시작할 수는 없습니다 vfork().

자식 프로세스가 실행되는 동안 자식 프로세스가 부모 프로세스의 주소 공간을 차용하기 때문에 부모 프로세스가 차단됩니다.

무엇을 하든 단순히 스택의 모든 항목에 액세스하면 하위 항목의 비공개 스택만 수정됩니다. 그러나 글로벌 데이터를 수정하면 공통 데이터가 수정되므로 상위 데이터에도 영향을 미칩니다.

다음과 같이 전역 데이터를 수정하는 것:

  • malloc() 또는 free()를 호출합니다.

  • 표준 입력 및 출력 사용

  • 신호 설정 수정

  • 호출 함수에 로컬이 아닌 변수를 수정합니다 vfork().

  • ...

을 호출하면 _exit()(중요하게는 절대 호출하지 않음 exit()) 하위 프로세스가 종료되고 제어권이 상위 프로세스로 반환됩니다.

이 시리즈의 함수가 호출 되면 exec*()새 프로그램 코드, 새 데이터 및 상위 스택의 일부를 사용하여 새 주소 공간이 생성됩니다(아래 참조). 준비되면 하위 프로세스는 더 이상 하위 프로세스에서 주소 공간을 빌려오지 않고 자체 주소 공간을 사용합니다.

상위 프로세스의 주소 공간이 더 이상 다른 프로세스에서 사용되지 않기 때문에 제어권이 상위 프로세스로 반환됩니다.

중요 사항: Linux에서는 실제 구현이 없습니다 vfork(). Linux는 1988년 SunOS-4.0에 도입된 Copy on Write 개념을 vfork()기반으로 구현되었습니다. fork()사용자가 Linux를 사용하고 있다고 믿게 만들기 위해 Linux는 공유 데이터를 설정하고 하위 항목이 해당 기능 중 하나를 vfork()호출하지 않을 때 상위 항목을 일시 중지합니다 ._exit()exec*()

vfork()따라서 Linux는 실수에 커널의 하위 프로세스에 대한 주소 공간 설명이 필요하지 않다는 사실 로부터 이점을 얻지 못합니다 . 이로 인해 a 는 vfork()보다 빠르지 않게 됩니다 fork(). real 을 구현하는 시스템에서는 vfork()일반적으로 -, Nearest 및 - 를 사용하는 셸보다 3배 빠르며 fork()성능에 영향을 미칩니다.vfork()ksh93Bourne Shellcsh

exit()ed 자식에서 호출하면 안 되는 이유는 호출 전에 플러시되지 않은 데이터가 있는 경우 stdio를 플러시하기 위한 vfork()것입니다 . 이로 인해 이상한 결과가 발생할 수 있습니다.exit()vfork()

참고: posix_spawn()그 위에 구현되므로 vfork()OS vfork()에서 제거되지 않습니다. 누군가 Linux vfork()에서는 posix_spawn().

스택에 대한 문서는 거의 없습니다. Solaris 매뉴얼 페이지에는 다음과 같은 내용이 나와 있습니다.

 The vfork() and vforkx() functions can normally be used  the
 same  way  as  fork() and forkx(), respectively. The calling
 procedure, however, should not return while running  in  the
 child's  context,  since the eventual return from vfork() or
 vforkx() in the parent would be to a  stack  frame  that  no
 longer  exists. 

따라서 구현은 원하는 대로 수행할 수 있습니다. Solaris 구현에서는 공유 메모리를 함수 호출을 위한 스택 프레임으로 사용합니다 vfork(). 상위 스택의 이전 부분에 대한 액세스 권한을 부여하는 구현은 없습니다.

관련 정보