Linux에서 fork ()가 전체 프로세스 힙을 즉시 복사합니까?


30

fork()시스템 호출은 실행중인 프로세스에서 자식 프로세스를 복제합니다. PID를 제외하고 두 프로세스는 동일합니다.

당연히 프로세스가 쓰지 않고 힙에서 읽는 경우 힙을 복사하면 메모리가 많이 낭비됩니다.

전체 프로세스 힙이 복사됩니까? 쓰기 만 힙 복사를 트리거하는 방식으로 최적화 되었습니까?

답변:


19

전체fork()mmap를 사용하여 구현됩니다 / 쓰기에 복사합니다.

이는 힙뿐만 아니라 공유 라이브러리, 스택, BSS 영역에도 영향을줍니다.

우연히도 결과 2 프로세스 (부모 및 자식)가 실제로 메모리 범위에 쓰기를 시작할 때까지 포크가 매우 가벼운 작업임을 의미합니다. 이 기능은 포크 폭탄의 치명적인 원인이됩니다. 페이지 복제 및 차별화로 커널이 오버로드되기 전에 너무 많은 프로세스가 필요합니다.

현대 OS에서 커널이 하드 카피를 수행하는 작업의 예 (장치 드라이버는 예외 임)를 찾기가 쉽지 않을 것입니다. VM 기능을 사용하는 것이 훨씬 쉽고 훨씬 효율적입니다.

심지어 execve()"이진 / ld.so / whatnot,이어서 실행"을 수행하십시오. VM은 프로세스를 RAM 및 실행에 실제로로드하는 것을 처리합니다. 초기화되지 않은 로컬 변수는 '제로 페이지'에서 mmaped-0을 포함하는 특수한 읽기 전용 copy-on-write 페이지, 로컬 초기화 된 변수는 이진 파일 자체에서 mmaped (write-on-write, 다시) 기타


주목할만한 예외 중 하나는 Java 프로세스입니다. "fork java memory"를 검색 하면 큰 서버 JVM 또는 임베디드 JVM 에 작은 쉘 명령을 실행하려고 시도하고 "메모리를 할당 할 수 없음" 예외 에서 비정상적으로 충돌하는 수십 가지 문제 가 있습니다 (임의의 링크 일뿐입니다.이 문제는 체계적입니다). 자바 환경에). 이 SO 답변 은 JVM의 가비지 수집기 및 JIT 컴파일러가 프로세스 메모리를 공유하지 못하도록 비난합니다.
WhiteWinterWolf

24

Linux 커널 fork()은 호출 시 복사시 쓰기를 구현 합니다. syscall이 실행될 때 부모와 자식이 공유하는 페이지는 읽기 전용으로 표시됩니다.

읽기 전용 페이지에서 쓰기가 수행되면 두 프로세스간에 메모리가 더 이상 동일하지 않으므로 복사됩니다. 따라서 읽기 작업 만 수행중인 경우 페이지가 전혀 복사되지 않습니다.


1
+1 감사합니다! 1. 참조 링크를 제공해 주시겠습니까? 2. 힙이 완전히 또는 부분적으로 복사됩니까?
Adam Matan

4
2.-페이지에서 :) 커널은 "힙"이 무엇인지에 대해 거의 이해하지 못합니다. 커널의 경우 libc 할당자가 원하는대로 처리하는 mmapped 개인 페이지입니다.
qdot

이것이 정말로 포크 폭탄입니까? 현재 프로세스를 포기하지 않고이 코드는 fork()호출 후 다음 명령이 아닌 시작부터 실행되는 동일한 프로그램의 인스턴스를 더 많이 생성하는 것으로 보입니다 .
sherrellbc

@mmk 참고로, "흥미로운 사이드 노트"에 상당히 놀랐고 (Linux 3.2.0에서) 테스트를 거쳤지만 사실이 아닙니다. 나는 사용 /proc/self/pagemap하여 시험의 목적의 물리적 페이지 매핑 가상 주소를 확인합니다. 예상대로, 손자와 손자 만 공유 페이지를 작성하면 부모와 원래의 자식은 계속 공유합니다. 손자 만 개인 사본으로 끝납니다.
Celada

@ 셀라 다. 흠. 나는 이것을 어딘가에서 읽었고, 커널 버전 (아마도 오래된 버전)을 기억하지 못하기 때문에 더 이상 유효하지 않을 수 있습니다.
mmk

10

Linux는 Copy-on-Write를 수행합니다. 으로 fork새로운 프로세스를 생성, 할당 된 페이지는 읽기 전용으로 표시하고, 부모와 자식 사이에 공유됩니다. 둘 중 하나가 페이지를 수정하려고하면 페이지 결함이 발생하여 페이지를 복사하고 페이지 테이블을 적절하게 조정합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.