나는 가상 메모리에 관한 교과서를 읽고 있었는데 다음과 같이 말했습니다.
모든 Linux 프로그램은 다음을 수행하는 함수를 호출하여 로더를 호출할 수 있습니다 execve
.
현재 프로세스 가상 주소의 사용자 부분에서 기존 영역 구조를 제거합니다.
새 프로그램의 코드, 데이터, bss 및 스택 영역에 대한 새 영역 구조를 만듭니다. 이 모든 새로운 영역은개인 쓰기 중 복사. 코드 및 데이터 영역은 a.out 파일의 .text 및 .data 섹션에 매핑됩니다.
fork()
나는 프로그램이 단일 프로세스 프로그램(사용되지 않음 )이라면 이 단일 프로세스가 가상 주소, 즉 .data
그 일부 에서 시작하면 a.out
보호 오류가 발생하고 오류 처리기가 보호 예외가 발생했음을 인식한다고 생각했습니다. 개인 쓰기 시간 복사 영역의 페이지에 쓰려고 하는 프로세스로 인해 발생하며, 이로 인해 실제 메모리에 페이지의 새 복사본이 생성됩니다.
여기에는 두 가지 문제가 있습니다.
물리적 메모리에 동일한 페이지를 공유할 수 있는 두 번째 프로세스가 없더라도 개인 영역의 기록 중 복사 메커니즘은 여전히 새 페이지를 생성합니다. 이는 프로세스가 하나만 있고 프로세스가 없기 때문에 전혀 유용하지 않습니다. 다른 프로세스는 새 페이지를 생성합니다. 이 페이지에 쓸 때 프로세스가 페이지를 수정하려고 할 때마다 처리를 위해 예외가 발생합니다. 이것이 매우 비효율적입니까?
페이지의 새 복사본이 물리적 메모리에 생성되면 프로세스에서 더 이상 참조하지 않는 원본 페이지는 어떻게 되나요? 이전 페이지가 실제 메모리에 있으면 메모리 낭비가 아닌가요?
답변1
중요한 정보가 누락되었습니다. 커널이 쓰기 중 복사 시나리오에 해당하는 페이지 오류를 처리할 때 대상 페이지가 단일 프로세스에서 사용되는 경우 페이지를 복사하는 대신 쓰기 가능하게 만듭니다.
커널은 각 페이지에 대한 카운터를 유지합니다.mapcount
존재하다struct page
;단일 프로세스가 페이지를 매핑하는 경우 이 카운터는 0이고 새 프로세스가 페이지를 매핑할 때마다 증가하고 매핑이 해제되면 감소합니다(예를 들어쓰기 중 복사이고 프로세스가 쓰기를 시도하기 때문입니다.