fork(시스템콜)

fork (system call)

컴퓨팅에서, 특히 Unix 운영 체제와 그 작업 환경에서, 포크는 프로세스가 자신의 복사본을 만드는 작업입니다.POSIX단일 UNIX 사양 표준을 준수하기 위해 필요한 인터페이스입니다.보통 C Standard Library(libc; 표준 라이브러리) 래퍼로 커널의 포크, 클론 또는 기타 시스템 호출에 구현됩니다.Fork는 Unix와 유사한 운영 체제에서 프로세스를 생성하는 주요 방법입니다.

개요

멀티태스킹 운영체제에서 프로세스(프로그램 실행)는 다른 프로그램을 실행하는 등 새로운 프로세스를 생성하는 방법을 필요로 합니다.Unix 계열 시스템에서는 일반적으로 Fork와 그 변형만 가능합니다.다른 프로그램의 실행을 시작하는 프로세스는 먼저 자신의 복사본을 만들기 위해 분기합니다.그런 다음 "자녀 프로세스"라고 불리는 복사는 exec 시스템 호출을 호출하여 다른 프로그램과 오버레이합니다. 즉, 이전 프로그램의 실행을 중지하고 다른 프로그램을 선택합니다.

포크 조작에서는, 아이에 대해서 개별의 주소 공간이 작성됩니다.하위 프로세스에는 상위 프로세스의 모든 메모리 세그먼트의 정확한 복사본이 있습니다.SunOS-4.0의 가상 메모리 모델을 따르는 최신 UNIX 버전에서는 Copy-on-Write 시멘틱스가 구현되어 물리 메모리를 실제로 복사할 필요가 없습니다.대신에, 양쪽 프로세스의 가상 메모리 페이지는, 어느쪽이 그러한 페이지에 기입할 때까지, 같은 물리 메모리의 페이지를 참조할 수 있습니다.그 후, 그 페이지가 카피됩니다.이 최적화는 새로운 프로그램을 실행하기 위해 fork를 execute와 함께 사용하는 일반적인 경우에 중요합니다.일반적으로 자녀 프로세스는 시작할 프로그램을 위해 프로그램 실행을 중지하기 전에 작은 액션 세트만 수행합니다.또한 부모 데이터 구조를 필요로 하는 경우는 거의 없습니다.

프로세스가 포크를 호출하면 상위 프로세스로 간주되며 새로 생성된 프로세스가 하위 프로세스입니다.포크 후 두 프로세스 모두 동일한 프로그램을 실행할 뿐만 아니라 시스템콜을 호출한 것처럼 실행을 재개합니다.그런 다음 콜의 반환값을 검사하여 자신의 상태(자녀 또는 부모)를 판단하고 그에 따라 행동할 수 있습니다.

역사

포크 개념에 대한 최초의 언급 중 하나는 1962년에 [1]출판된 Melvin Conway의 A Multiprocessor System Design에 나타나 있습니다.Conway의 논문은 GENI 시분할 시스템 포크를 L. Peter Deutsch에 의해 구현된 동기가 되었으며, 이 개념은 Ken Thompson에 의해 차용되어 Research [3][4]Unix에 최초[2] 등장했습니다.포크는 나중에 POSIX[5]표준 인터페이스가 되었습니다.

의사소통

하위 프로세스는 상위 파일 [5]설명자의 복사본으로 시작합니다.프로세스 간 통신의 경우 상위 프로세스에서 하나 또는 여러 개의 파이프를 생성한 후 [6]프로세스가 필요하지 않은 파이프의 끝을 닫는 경우가 많습니다.

변종

Vfork

Vfork는 동일한 호출 규칙과 거의 동일한 의미를 가진 포크의 변형이지만 제한된 상황에서만 사용됩니다.가상 메모리를 지원하는 최초의 [7][8][9]Unix인 Unix의 3BSD 버전에서 비롯되었습니다.POSIX에 의해 표준화되어 vfork가 포크와 완전히 동일한 동작을 할 수 있게 되었지만 2004년[10] 에디션에서는 objective로 마크되어 후속 에디션에서는 posix_spawn()으로 대체되었습니다(일반적으로 vfork를 통해 구현됩니다.

vfork 시스템콜이 발행되면 자 프로세스가 실행을 완료하거나 시스템콜의 "exec" 패밀리 중 하나를 통해 새로운 실행 가능 이미지로 대체될 때까지 부모 프로세스가 일시 중단됩니다.그 아이는 부모로부터 메모리 페이지는 부모님과 자식 프로세스 사이에서 아무런 복제도 하고 없copy-on-write 의미 특히 기술에와 공유됩니다;[10]따라서 그 아이는 과정 어떤 공유된 페이지의 수정을 할 때, 어떤 새로운 페이지 및 수정 페이지를 부모 프로세스에서 볼 수 있 만들어질 MMU 설정을 빌린다. 너무페이지 복사가 전혀 수반되지 않기 때문에(메모리의 증설이 필요), 이 기술은 exec과 함께 사용할 때 풀 카피 환경에서 플레인 포크를 최적화합니다.POSIX 에서는, exec 패밀리에서 함수를 즉시 호출하기 위한 전주곡(및 선택한 몇개의 다른 조작) 이외의 목적으로 vfork 를 사용하면,[10] 정의되지 않은 동작이 발생합니다.vfork와 마찬가지로 아이는 데이터 구조를 복사하는 대신 빌립니다. vfork는 여전히 쓰기 시멘틱스 복사를 사용하는 포크보다 빠릅니다.

시스템 VR4가 [citation needed]도입되기 전에 시스템 V는 이 함수 호출을 지원하지 않았습니다.는 메모리 공유에 오류가 발생하기 쉽기 때문입니다.

Vfork는 페이지 테이블을 복사하지 않으므로 System V 포크 구현보다 빠릅니다.그러나 하위 프로세스는 상위 프로세스와 동일한 물리적 주소 공간에서 실행되므로(exec 또는 exit까지) 상위 프로세스와 스택을 덮어쓸 수 있습니다.프로그래머가 vfork를 잘못 사용하면 위험한 상황이 발생할 수 있으므로 vfork를 호출할 책임은 프로그래머에게 있습니다.System V 접근법과 BSD 접근법의 차이점은 다음과 같습니다.커널은 구현의 특이성을 사용자에게 숨길 것인가, 아니면 고급 사용자가 구현의 이점을 활용하여 논리적인 기능을 보다 효율적으로 수행할 수 있도록 해야 하는가?

--

마찬가지로 vfork의 Linux man 페이지도 사용을 [7][failed verification][discuss]강하게 권장하지 않습니다.

리눅스가 과거의 이 망령을 되살린 것은 다소 유감스러운 일이다.BSD man 페이지에는 다음과 같이 기술되어 있습니다.「이 시스템콜은, 적절한 시스템 공유 메카니즘이 실장되면 없어집니다.사용자는 vfork()의 메모리 공유 시멘틱에 의존하지 마십시오.이 경우, 이 시멘틱은 fork(2)"

기타 문제vfork에는 동적 [12]링크와의 상호 작용으로 인해 다중 스레드 프로그램에서 발생할 수 있는 교착 상태가 포함됩니다.vfork 인터페이스를 대체하기 위해 POSIX는 fork와 exec의 액션을 조합한 posix_spawn 함수 패밀리를 도입했습니다.이러한 함수는 Linux에서처럼 [12]라이브러리 루틴으로 구현되거나 [12][13]Solaris에서처럼 더 나은 성능을 위해 vfork에서 구현될 수 있지만 POSIX 사양에서는 특히 제한된 하드웨어 및 실시간 [14]시스템에서 실행되는 운영 체제용으로 "커널 운영으로 설계"되었다고 명시되어 있습니다.

반면 4.4는BSD 구현으로 인해 vfork 구현이 제거되어 vfork가 포크와 동일한 동작을 수행하게 되었습니다. 나중에 성능상의 [8]이유로 NetBSD 운영 체제에서 복원되었습니다.

uClinux와 같은 일부 임베디드 운영 체제에서는 MMU가 없어 Copy-on-Write를 구현할 수 없는 디바이스에서 운영해야 하므로 포크는 생략하고 vfork만 구현합니다.

Rfork

그 계획은 9운영 체제, Unix의 디자이너들에 의해 창조된 포크지만 또한 주소 공간(각 과정에 독특한 스택 세그먼트를 제외하고,), 환경 변수와 파일 시스템 네임 스페이스를 비롯하여 자원의 부모님과 자식 프로세스 사이의 결이 고운 공유할 수 있는 변형이라고 불리는"rfork";[15]이 회사를 포함한다.앉으세요.프로세스[16]스레드를 모두 작성할 수 있는 통합 인터페이스입니다.FreeBSD[17] IRIX는 모두 플랜 9에서 RFork 시스템 호출을 채택했으며, 후자의 이름은 "sproc"[18]로 변경되었습니다.

클론

cloneLinux 커널 내의 시스템콜로 실행 컨텍스트의 일부를 부모와 공유할 수 있는 자 프로세스를 만듭니다.FreeB처럼SD의 rfork와 IRIX의 sproc, Linux의 클론은 Plan 9의 rfork에서 영감을 받아 스레드 구현에 사용할 수 있습니다(단, 애플리케이션 프로그래머는 일반적으로 클론 위에 구현된 pthread 등의 고급 인터페이스를 사용합니다).(Linus Torvalds에 따르면) 너무 많은 [18]오버헤드가 발생하기 때문에 Plan 9 및 IRIX의 "별도의 스택" 기능은 생략되었습니다.

다른 운영 체제에서의 포킹

VMS 운영체제의 원래 설계(1977년)에서는 포킹과 같이 새로운 프로세스에 대한 몇 가지 특정 주소의 내용을 나중에 변환하는 복사 조작은 [citation needed]위험하다고 간주되었다.현재 프로세스 상태의 오류가 하위 프로세스에 복사될 수 있습니다.여기서 프로세스 산란 은유를 사용한다.새로운 프로세스의 메모리 레이아웃의 각 컴포넌트는 처음부터 새롭게 구성된다.sean 은유는 나중에 마이크로소프트 운영체제(1993)에서 채택되었다.

VM/CMS(OpenExtensions)의 POSIX 호환 컴포넌트는 포크를 매우 제한적으로 구현합니다.이 경우 자녀가 실행되는 동안 부모가 일시 중단되고 자녀와 부모가 동일한 주소 [19]공간을 공유합니다.이는 기본적으로 포크로 라벨이 지정된 vfork입니다(이는 CMS 게스트 운영 체제에만 적용되며 Linux와 같은 다른 VM 게스트 운영 체제에서는 표준 포크 기능을 제공합니다).

응용 프로그램 사용 현황

다음 변형 Hello World 프로그램은 C 프로그래밍 언어로 포크 시스템 호출의 메커니즘을 보여줍니다.프로그램은 2개의 프로세스로 나누어지며, 각각 포크 시스템 호출의 반환 값에 따라 어떤 기능을 수행할지 결정합니다.헤더 포함 등 보일러 플레이트 코드가 누락되었습니다.

인트 주된(무효) {     pid_t pid = 포크();      한다면 (pid == -1) {         에러("실패");         퇴장(EXIT_FAILURE);     }     또 다른 한다면 (pid == 0) {         인쇄물("자녀 프로세스에서 안녕하세요!\n");         _개요(종료_SUCCESS);     }     또 다른 {         인트 상황;         (무효)waitpaid(pid, &상황, 0);     }     돌아가다 종료_SUCCESS; } 

다음은 이 프로그램의 내용입니다.

   pid_t pid = 포크(); 

번째 문은 포크 시스템 호출을 호출하여 실행을 2개의 프로세스로 분할합니다.포크의 반환값은 프로세스 식별자(PID)의 POSIX 유형인 pid_t 변수에 기록됩니다.

    한다면 (pid == -1) {         에러("실패");         퇴장(EXIT_FAILURE);     } 

1 빼기는 포크 오류를 나타냅니다.새로운 프로세스가 생성되지 않았으므로 오류 메시지가 출력됩니다.

포크가 성공적이었으면 이제 두 개의 프로세스가 있으며 두 프로세스 모두 포크가 반환된 시점부터 주요 기능을 실행합니다.프로세스가 다른 태스크를 수행하도록 하려면 프로그램은 포크 반환값을 분기하여 하위 프로세스 또는 상위 프로세스로 실행 중인지 판단해야 합니다.

   또 다른 한다면 (pid == 0) {       인쇄물("자녀 프로세스에서 안녕하세요!\n");       _개요(종료_SUCCESS);    } 

하위 프로세스에서는 반환 값이 0(잘못된 프로세스 식별자)으로 표시됩니다.자녀 프로세스는 원하는 그리팅 메시지를 인쇄한 후 종료합니다(기술상의 이유로 여기서 C 표준 종료 함수 대신 POSIX _exit 함수를 사용해야 합니다).

   또 다른 {       인트 상황;       (무효)waitpaid(pid, &상황, 0);    } 

다른 프로세스인 부모는 항상 양수인 자녀의 프로세스 식별자를 포크로부터 수신합니다.부모 프로세스는 이 식별자를 waitpid 시스템콜에 전달하고 아이가 종료할 때까지 실행을 일시 정지합니다.이 경우 부모는 실행을 재개하고 반환문을 사용하여 종료합니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ Nyman, Linus (25 August 2016). "Notes on the History of Fork and Join". IEEE Annals of the History of Computing. 38 (3): 84–87. doi:10.1109/MAHC.2016.34.
  2. ^ "s3.s from Research UNIX". GitHub. 1970.
  3. ^ Ken Thompson and Dennis Ritchie (3 November 1971). "SYS FORK (II)" (PDF). UNIX Programmer's Manual. Bell Laboratories.
  4. ^ Ritchie, Dennis M.; Thompson, Ken (July 1978). "The UNIX Time-Sharing System" (PDF). Bell System Tech. J. AT&T. 57 (6): 1905–1929. doi:10.1002/j.1538-7305.1978.tb02136.x. Retrieved 22 April 2014.
  5. ^ a b fork – System Interfaces Reference, 단일 UNIX 사양, The Open Group 버전 4
  6. ^ pipe – System Interfaces Reference, 단일 UNIX 사양, The Open Group 버전 4
  7. ^ a b vfork(2)Linux 프로그래머 매뉴얼– 시스템 콜
  8. ^ a b "NetBSD Documentation: Why implement traditional vfork()". NetBSD Project. Retrieved 16 October 2013.
  9. ^ "vfork(2)". UNIX Programmer's Manual, Virtual VAX-11 Version. University of California, Berkeley. December 1979.
  10. ^ a b c vfork – System Interfaces Reference, 단일 UNIX 사양, The Open Group 버전 3
  11. ^ Bach, Maurice J. (1986). The Design of The UNIX Operating System. Prentice–Hall. pp. 291–292. Bibcode:1986duos.book.....B.
  12. ^ a b c Nakhimovsky, Greg (2006). "Minimizing Memory Usage for Creating Application Subprocesses". Oracle Technology Network. Oracle Corporation.
  13. ^ OpenSolaris posix_http() 구현:https://sourceforge.net/p/schillix-on/schillix-on/ci/default/tree/usr/src/lib/libc/port/threads/spawn.c
  14. ^ posix_spawn – System Interfaces Reference, 단일 UNIX 사양, The Open Group 버전 4
  15. ^ fork(2)Plan 9 프로그래머 매뉴얼, 1권
  16. ^ intro(2)Plan 9 프로그래머 매뉴얼, 1권
  17. ^ rfork(2)FreeBSD 시스템 콜 매뉴얼
  18. ^ a b Torvalds, Linus (1999). "The Linux edge". Open Sources: Voices from the Open Source Revolution. O'Reilly. ISBN 978-1-56592-582-3.
  19. ^ "z/VM > z/VM 6.2.0 > Application Programming > z/VM V6R2 OpenExtensions POSIX Conformance Document > POSIX.1 Conformance Document > Section 3. Process Primitives > 3.1 Process Creation and Execution > 3.1.1 Process Creation". IBM. Retrieved April 21, 2015.