하위 프로세스가 작성된 직후 exec () 또는 exit ()를 호출 할 때 vfork ()를 사용하려는 이유는 무엇입니까? 사용합니다. vfork ()는 COW

운영 체제 개념과 APUE의 말

vfork ()를 사용하면 부모 프로세스가 일시 중단되고 자식 프로세스는 부모의 주소 공간을 사용합니다. vfork ()는 COW (Copy-On-Write)를 사용하지 않기 때문에 자식 프로세스가 부모 주소 공간의 페이지를 변경하면 변경된 페이지가 다시 시작되면 부모에게 표시됩니다. 따라서 자식 프로세스가 부모의 주소 공간을 수정하지 않도록 vfork ()를주의해서 사용해야합니다.

vfork ()는 자식 프로세스가 생성 직후에 exec () 또는 exit ()를 호출 할 때 사용됩니다.

마지막 문장을 어떻게 이해해야합니까?

vfork()calls exec()에 의해 생성 된 자식 프로세스 exec()가 새 프로그램을로드하여 부모 프로세스의 주소 공간을 수정 하지 않습니까?

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

나는 리눅스를 선호한다.

감사.



답변

vfork()calls exec()에 의해 생성 된 자식 프로세스 exec()가 새 프로그램을로드하여 부모 프로세스의 주소 공간을 수정 하지 않습니까?

아니요, exec()새 프로그램에 새로운 주소 공간을 제공합니다. 부모 주소 공간은 수정하지 않습니다. 예를 들어, 참조 의 토론 execPOSIX 함수리눅스 execve()맨 페이지를 .

vfork ()에 의해 생성 된 자식 프로세스가 exit ()를 호출 할 때, 자식을 종료 할 때 exit ()가 부모 프로세스의 주소 공간을 수정하지 않습니까?

일반 exit()– 실행중인 프로그램 (라이브러리 포함)에 의해 설치된 종료 후크를 실행합니다. vfork()더 제한적입니다. 따라서, 리눅스, 그것은 의무화 를 사용 _exit()하는 하지 않는 C 라이브러리의 정리 함수를 호출합니다.

vfork()옳은 게 어려웠습니다. POSIX 표준의 현재 버전에서 제거되었으며 posix_spawn()대신 사용해야합니다.

당신이하지 않는 그러나, 정말 당신이 무슨 일을하는지 알고, 당신은해야 하지 하나를 사용 vfork()하거나 posix_spawn(); 좋은 오래된 고집 fork()하고 exec().

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

그러나, 낡은 옛날 fork(2)
에는 호출자의 데이터 공간의 완전한 사본을 만들 필요 exec(3)가있을 것입니다. 따라서 BSD는 효율성을 높이기 vfork()
위해 부모 프로세스의 주소 공간을 완전히 복사하지는 않았지만 호출 execve(2)또는 종료가 발생할 때까지 부모의 메모리와 제어 스레드를 빌린 시스템 호출을 도입 했습니다. 자식이 리소스를 사용하는 동안 부모 프로세스가 일시 중단되었습니다. 의 사용은
vfork()신중해야 예를 들어, 상위 공정에서 변형되지 데이터는 레지스터에 유지 된 변수에 의존 알고.


답변

를 호출 vfork()하면 새 프로세스가 작성되고 새 프로세스가 스택을 제외하고 상위 프로세스의 프로세스 이미지를 차용합니다. 자식 프로세스에는 새로운 스택 스타가 부여되지만 return호출 한 함수에서 허용하지 않습니다 vfork().

자식이 실행되는 동안 자식이 부모의 주소 공간을 빌 렸을 때 부모 프로세스가 차단됩니다.

당신이 무엇을하든, 단지 스택에 액세스하는 모든 것은 자식의 개인 스택만을 수정합니다. 그러나 전역 데이터를 수정하면 공통 데이터가 수정되므로 상위 데이터에도 영향을줍니다.

글로벌 데이터를 수정하는 것은 다음과 같습니다.

  • malloc () 또는 free () 호출

  • stdio 사용

  • 신호 설정 수정

  • 호출되는 함수에 로컬하지 않은 변수들을 수정 vfork().

호출하면 _exit()(중요, 호출하지 않음 exit()) 자식이 종료되고 부모에게 제어권이 다시 부여됩니다.

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

주소 공간이 더 이상 다른 프로세스에서 사용되지 않으므로 제어는 상위에 다시 제공됩니다.

중요 : Linux에서는 실제 vfork()구현 이 없습니다 . 리눅스가 아니라 구현 vfork()쓰기에 복사를 기반으로 fork()개념을 만들기 위해 SunOS의-4.0 1988 년 도입 사용자는 사용하는 것이 생각 vfork()리눅스 그냥 공유 데이터를 설정하고 아이가 전화를하지 않은 상태에서 부모를 일시 중단, _exit()또는 한 exec*()기능.

따라서 리눅스는 실제 vfork()커널에서 자식에 대한 주소 공간 설명을 설정할 필요가 없다는 사실로부터 이익을 얻지 못한다. 결과는 vfork()보다 빠르지 않습니다 fork(). 진짜를 구현하는 시스템에서 vfork(), 그것은보다 빠른 일반적으로 3 배이다 fork()포탄의 성능에 그 사용에 영향 vfork()ksh93최근의 Bourne Shellcsh.

ed 자녀에게 전화 exit()를 걸어서 vfork()는 안되는 이유는 전화 exit()하기 전에 데이터가 유출되지 않은 경우 stdio 를 플러시하기 때문 vfork()입니다. 이상한 결과가 발생할 수 있습니다.

BTW : posix_spawn()는 위에 구현되어 vfork()있으므로 vfork()OS에서 제거되지 않습니다. 리눅스가 사용하지 않는 것으로 언급 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(). 어떤 구현도 부모로부터 스택의 오래된 부분에 대한 액세스 권한을 부여하지 않습니다.


답변