Linux에서 fork()를 호출하면 두 프로세스(하나는 다른 프로세스의 하위 프로세스)가 할당된 힙 메모리를 공유합니다. 이렇게 할당된 페이지는 COW(기록 중 복사)로 표시되며 두 프로세스 중 하나가 페이지를 수정할 때까지 공유된 상태로 유지됩니다. 이 시점에서는 복사되지만 이를 참조하는 가상 주소 포인터는 변경되지 않은 상태로 유지됩니다. MMU(Memory Management Unit)는 이 둘을 어떻게 구별합니까? 다음을 고려하세요:
- 프로세스 A가 시작되었습니다
- 프로세스 A는 가상 주소 0x1234가 가리키는 메모리 페이지를 할당합니다.
- 프로세스 A는 프로세스 B를 생성하기 위해 포크()합니다.
- 프로세스 A와 B는 이제 동일한 물리적 메모리 위치를 가리키는 가상 주소 0x1234를 공유합니다.
- 프로세스 B는 0x1234 메모리 페이지를 수정합니다.
- 메모리 페이지가 복사된 후 수정됩니다.
- 프로세스 A와 B는 모두 가상 주소 0x1234를 가지고 있지만 이는 서로 다른 물리적 메모리 주소를 가리킵니다.
이것을 어떻게 구별하나요?
답변1
프로세스 간 컨텍스트 전환 중에 커널이 수행하는 작업 중 하나는 MMU 테이블을 수정하여 이전 프로세스의 주소 공간을 설명하는 항목을 제거하고 다음 프로세스의 주소 공간을 설명하는 항목을 추가하는 것입니다. 프로세서 아키텍처, 코어 및 가능한 구성에 따라 프로세서 레지스터를 변경하거나 메모리의 페이지 테이블을 조작하여 이를 수행할 수 있습니다.
포크 작업 후 쓰기 중 복사로 인해 두 프로세스의 MMU 테이블은 동일한 물리적 주소(가상 주소 0x1234)를 갖게 됩니다. 다시 말하지만, 이들은 이 특정 가상 주소에 대해 동일한 항목을 갖는 두 개의 별도 테이블입니다.
이 페이지의 설명자에는 읽기 전용 속성이 있습니다. 프로세스가 쓰기(A 또는 B)를 시도하면 권한 위반으로 인해 프로세서 오류가 발생합니다. 커널의 페이지 오류 핸들러가 실행되고, 상황을 분석하고, 새로운 물리적 페이지를 할당하기로 결정하고, 읽기 전용 페이지의 내용을 이 새 페이지에 복사하고, 호출 프로세스의 MMU 구성을 변경하여 이제 0x1234가 새로 할당된 페이지를 가리키도록 합니다. 읽기가 포함된 물리적 페이지 속성 페이지를 작성하고 오류를 일으킨 명령에 대해 호출 프로세스를 다시 시작합니다. 이번에는 페이지에 쓰기가 가능하므로 지시문이 정체되지 않습니다.
다른 프로세스의 페이지 설명자는 이 작업의 영향을 받지 않습니다. 실제로 그럴 수도 있습니다. 커널도 작업을 수행하기 때문입니다. 즉, 페이지가 현재 단일 프로세스에만 매핑된 경우 나중에 복사하는 것을 방지하기 위해 읽기-쓰기 상태로 다시 전환됩니다.
당신은 또한 볼 수 있습니다페이지 폴트 후에는 어떻게 되나요?