메모리 매핑 및 Copy-on-write (COW)
공유 객체
공유 객체란?
- 물리 메모리에 존재하는 하나의 객체가 여러 프로세스의 가상 메모리에 매핑될 수 있습니다.
- 서로 다른 가상 주소에 동일한 물리 메모리 객체를 매핑할 수 있습니다.
예시: 프로세스 1과 프로세스 2가 동일한 공유 객체를 매핑
- 프로세스 1과 프로세스 2는 동일한 공유 객체를 각각의 가상 메모리에 매핑합니다.
- 가상 주소는 다를 수 있지만, 동일한 물리 메모리 객체를 공유합니다.
Copy-on-write (COW) 객체
COW 객체란?
- 프로세스가 객체를 읽기 전용으로 공유하지만, 쓰기 시 새로운 복사본을 생성하여 독립적인 수정이 가능하도록 하는 메커니즘입니다.
- 페이지 테이블 엔트리(PTE)에서 이러한 영역은 읽기 전용으로 표시됩니다.
예시: 두 프로세스가 동일한 COW 객체를 매핑
- 프로세스 1과 프로세스 2는 동일한 COW 객체를 매핑하지만, 해당 객체는 읽기 전용으로 표시됩니다.
- 쓰기 작업이 발생하면 보호 오류가 트리거되고, 핸들러는 새로운 읽기/쓰기 페이지를 생성합니다.
- 복사는 가능한 한 지연됩니다.
프로세스 복제와 메모리 매핑
fork 함수
fork는 각 프로세스에 독립적인 주소 공간을 제공하는 방법을 설명합니다.
- 새로운 프로세스를 위한 가상 주소 생성
- 현재의
mm_struct, vm_area_struct, 페이지 테이블을 정확하게 복사
- 두 프로세스의 각 페이지를 읽기 전용으로 표시
- 두 프로세스의 각
vm_area_struct를 private COW로 표시
- 반환 시, 각 프로세스는 가상 메모리의 정확한 복사본을 가집니다.
- 이후의 쓰기 작업은 COW 메커니즘을 사용하여 새로운 페이지를 생성합니다.
execve 함수
- 현재 프로세스에서 새로운 프로그램을 로드하고 실행
- 이전 영역의
vm_area_struct 및 페이지 테이블을 해제
- 새로운 영역을 위한
vm_area_struct 및 페이지 테이블 생성
- 프로그램과 초기화된 데이터는 객체 파일로부터 지원됩니다.
.bss와 스택은 익명 파일로부터 지원됩니다.
- PC를
.text의 진입 지점으로 설정
- 필요한 경우 Linux는 코드와 데이터 페이지를 페이징합니다.
사용자 레벨 메모리 매핑
mmap 함수
- 파일 기술자
fd로 지정된 파일의 오프셋 offset에서 시작하여 길이 len의 바이트를 매핑
- 매핑된 영역의 시작 주소를 반환 (시작 주소는 다를 수 있음)
- 프로토콜:
PROT_READ, PROT_WRITE, ...
- 플래그:
MAP_ANON, MAP_PRIVATE, MAP_SHARED, ...
예시: mmap을 사용한 파일 복사
- 사용자 공간으로 데이터를 전송하지 않고 파일을 표준 출력으로 복사
void mmapcopy(int fd, int size) {
char *bufp;
bufp = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
write(1, bufp, size);
return;
}
주소 변환
페이지 테이블을 사용한 주소 변환
- 가상 페이지 번호(VPN)와 물리 페이지 번호(PPN)를 통해 주소 변환
- 페이지 테이블의 유효 비트가 0인 경우, 페이지가 메모리에 존재하지 않음(페이지 폴트)
- 유효 비트가 1인 경우, 물리 페이지 번호(PPN)를 사용하여 주소 변환
스택 메모리
C 스택
- 커널은 프로그램 스택을 관리하며, 필요에 따라 확장됩니다.
- 커널은 MMU를 구성하여 프로그램 스택을 관리합니다.
- 프로세스 생성 시, 커널은 프로그램의 스택 크기를 결정하고, 스택 페이지를 존재하지 않지만 읽기 및 쓰기 가능한 상태로 표시합니다.
- 프로그램 스택이 커지면, 페이지 폴트를 통해 새로운 페이지가 할당됩니다.