프로세스가 분기되면 가상 메모리 또는 상주 메모리가 복사됩니까?

프로세스가 분기되면 가상 메모리 또는 상주 메모리가 복사됩니까?

Linux에서 새 프로세스를 생성하는 표준 방법은 상위 프로세스의 메모리 공간을 복사하고 execv호출될 때까지 하위 프로세스의 환경이 되는 것입니다.

가상 메모리(프로세스에서 요청한 메모리) 또는 상주 메모리(실제로 사용 중인 메모리) 중 어떤 메모리 공간을 말하는 걸까요?

동기: 스왑 공간이 제한된 장치와 가상 메모리 공간과 상주 메모리 공간의 차이가 큰 응용 프로그램이 있습니다. 메모리 부족으로 인해 애플리케이션이 분기될 수 없으며 가상 공간 크기를 줄이는 것이 도움이 되는지 확인하고 싶습니다.

답변1

최신 시스템에서는 fork 시스템 호출을 사용한 결과 실제로 메모리가 복사되지 않습니다. 페이지 테이블에는 모두 읽기 전용으로 표시되어 있으므로 커널 코드에 처음 쓰려고 할 때 트랩이 발생합니다. 복사는 첫 번째 프로세스가 쓰기를 시도할 때만 발생합니다.

이를 기록 중 복사라고 합니다.

그러나 커밋된 주소 공간을 추적해야 할 수도 있습니다. 커널이 페이지를 복사해야 할 때 사용 가능한 메모리나 스왑이 없으면 메모리를 확보하기 위해 일부 프로세스를 종료해야 합니다. 이는 항상 바람직한 것은 아니므로 커널이 커밋한 메모리 양을 추적하는 것이 가능합니다.

커널이 사용 가능한 메모리 + 스왑 공간보다 더 많은 메모리를 커밋하는 경우 포크를 호출하려고 할 때 오류 코드가 표시될 수 있습니다. 여유 공간이 충분하면 커널은 상위 프로세스의 전체 가상 크기를 포크 후 두 프로세스 모두에 커밋합니다.

답변2

걱정하지 마십시오. 지연 복사(기록 중 복사)를 수행합니다. 두 프로세스의 가상 메모리 주소는 처음에는 동일한 페이지를 가리키지만 분기된 프로세스가 이를 수정하려고 시도하면 실제로 페이지의 물리적 복사본이 생성됩니다(이 시점부터 페이지는 두 RAM 위치에 상주하게 됩니다).

보고된 메모리 공간은 실제로 프로세스가 사용하는 RAM의 양을 알려주지 않습니다. 가상 메모리 스와핑, 메모리 공유 등의 문제로 확실하게 판단하는 것은 불가능합니다. 메모리 공간의 일부 부분은 공유 라이브러리이고(어디로 계산됩니까?) 일부는 RAM이 아닌 메모리(기타 하드웨어 장치)를 참조하고 일부는 현재 교체되었으며 일부는 아직 복사되지 않았으며(기록 중 복사) 일부는 곧 될 것입니다. 이것을 읽어보세요:

https://lwn.net/Articles/642202/

답변3

커널 설정이 있습니다

/proc/sys/vm/overcommit_memory

우수한 인용기사:

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

이는 일반 malloc뿐만 아니라 포크에서도 작동합니다. 즉, 0으로 설정하면 포크는 쓰기 시 복사합니다. 기록 중 복사는 응용 프로그램이 포크되면 하위 버전이나 원래 버전이 메모리 변경을 시작할 때까지 두 복사본이 메모리 페이지를 공유한다는 의미입니다.

대부분의 배포판에서 남용은 0이라는 것을 알고 있습니다. 그러나 2로 설정하면 모든 메모리 페이지가 실제 메모리에 의해 완전히 지원되며 어떤 경우에는 높은 메모리 압력에서 더 안정적이지만 과잉 커밋에 의존하는 일부 프로그램(gitk를 접했습니다)은 실패합니다.

관련 정보