Wikipedia에 따르면(틀렸을 수도 있음)
fork() 시스템 호출이 실행되면 상위 프로세스에 해당하는 모든 페이지의 복사본이 생성되어 운영 체제에 의해 하위 프로세스를 위한 별도의 메모리 위치에 로드됩니다. 그러나 어떤 경우에는 이것이 필요하지 않습니다. 자식 프로세스가 "
exec
" 시스템 호출(C 프로그램에서 실행 파일을 실행하는 데 사용됨)을 실행하거나fork()
.exec
실행될 명령이 이를 호출한 프로세스의 주소 공간을 대체하기 때문입니다 .이 경우 COW(기록 중 복사)라는 기술이 사용됩니다. 이 기술을 사용하면 포크가 발생할 때 상위 프로세스의 페이지가 하위 프로세스에 복사되지 않습니다. 대신 하위 프로세스와 상위 프로세스 간에 페이지가 공유됩니다. 프로세스(상위 또는 하위)가 페이지를 수정할 때마다 수정을 수행한 프로세스(상위 또는 하위)에 대해 해당 특정 페이지의 별도 복사본이 별도로 생성됩니다. 그러면 이 프로세스는 향후 모든 참조에서 공유 페이지 대신 새로 복사된 페이지를 사용합니다. 다른 프로세스(공유 페이지를 수정하지 않은 프로세스)는 페이지의 원본 복사본(이제 더 이상 공유되지 않음)을 계속 사용합니다. 프로세스가 페이지에 쓸 때 페이지가 복사되기 때문에 이 기술을 기록 중 복사라고 합니다.
두 프로세스 중 하나가 페이지에 쓰기를 시도하면 페이지의 새 복사본이 할당되어 페이지 오류를 생성한 프로세스에 제공되는 것으로 보입니다. 그러면 원본 페이지가 쓰기 가능으로 표시됩니다.
내 질문은: fork()
프로세스가 공유 페이지에 쓰기를 시도하기 전에 여러 번 호출되면 어떻게 됩니까?
답변1
특별한 일은 일어나지 않습니다. 모든 프로세스는 동일한 페이지 집합을 공유하며 각 프로세스는 페이지를 수정하려고 할 때 자체 개인 복사본을 얻습니다.
답변2
fork()의 동작은 *nix 시스템에 MMU가 있는지 여부에 따라 달라집니다. MMU가 아닌 시스템(예: 초기 PDP-11)에서 fork() 시스템 호출은 각 하위 프로세스에 대한 모든 상위 프로세스의 메모리를 복사합니다. MMU 기반 *nix 시스템에서 커널은 스택이 아닌 모든 페이지를 R/O로 표시하고 이를 부모와 자식 간에 공유합니다. 그런 다음 두 프로세스 중 하나가 페이지에 쓰면 MMU가 해당 시도를 포착하고 커널은 쓰기 가능한 페이지를 할당하고 현재 쓰기 가능한 페이지를 가리키도록 MMU 페이지 테이블을 업데이트합니다. 이 쓰기 중 복사 동작은 처음에는 각 하위 프로세스에 대해 전용 스택만 할당하고 복제하면 되므로 속도가 향상됩니다.
각 fork() 호출 사이에 일부 상위 코드를 실행하면 결과 하위 프로세스는 상위 프로세스에 의해 변경된 페이지에 따라 달라집니다. 반면에 상위 프로세스가 여러 개의 fork() 호출(예: 루프)을 실행하는 경우 하위 프로세스는 거의 동일합니다. 로컬 루프 변수를 사용하는 경우 각 하위 스택의 변수는 달라집니다.
답변3
시스템이 포크를 수행할 때 일반적으로(구현에 따라 다를 수 있음) 페이지를 읽기 전용으로 표시하고 상위 프로세스를 해당 페이지의 기본 프로세스로 표시합니다.
이러한 페이지에 쓰려고 하면 페이지 오류가 발생하고 운영 체제가 대신하여 전체 페이지 목록을 복사하거나 변경된 페이지만 복사하므로(구현에 따라 다름) 쓰기 프로세스에서 쓰기 가능한 복사본을 갖게 됩니다.
동일한 프로세스에서 여러 프로세스가 분기되는 경우, "기본" 프로세스가 메모리에 쓸 때,다른프로세스는 해당 페이지를 복사합니다.