Demand-Zero Memory란?
Demand-Zero Memory란 "처음 접근할 때 0으로 초기화된 메모리"를 말한다.
정의
- Demand-zero memory는 프로그램이 요청하지만 아직 실제로 물리 메모리가 할당되지 않은 페이지이다.
- 이 메모리 페이지에 처음 접근하는 순간 운영체제가 실제 물리 메모리를 할당해 주며, 그 메모리의 모든 내용은 0으로 초기화된다.
즉, 프로그램이 메모리를 요청할 때 미리 0을 써놓지 않고, 실제로 쓸 때 0으로 된 메모리를 제공하는 것이다.
왜 'Demand' + 'Zero'인가?
- Demand: "필요할 때" (접근할 때) 물리 메모리를 할당함
- Zero: "초기값은 모두 0" 으로 채워진 메모리를 줌
예시 1.
int *arr = calloc(100, sizeof(int));
- calloc은 0으로 초기화된 100개의 int 배열을 요청한다.
- 운영체제는 실제로는 바로 400바이트를 물리적으로 메모리에 할당하지 않는다.
- 대신, 페이지 테이블에 'demand-zero page'라고 표시해 놓는다.
- 프로그램이 arr[0], arr[1] 등에 실제 접근하려 하면, 그 순간 Page Fault가 발생하고
- 운영체제가 0으로 초기화된 물리 메모리 페이지를 만들어서 매핑해 준다.
예시 2.
1. 프로그램이 메모리를 요청할 때
int big_array[1000000];
- 이 big_array는 굉장히 큰 메모리 공간을 필요로 한다.
- 컴파일러는 이걸 .bss 섹션에 놓거나, 스택/힙에 놓는다.
- 이때 운영체제는 실제 물리 메모리를 바로 할당하지 않는다.
- 대신 페이지 테이블(Page Table)에 "아직 없음"이라고 표시하거나,
특별히 "Demand-Zero 페이지" 타입으로 표시한다.
이렇게 하면 프로그램 입장에서는 big_array가 준비되어 있는 것처럼 보인다.
2. 메모리에 접근할 때 (Page Fault 발생)
프로그램이 처음으로 big_array[0] = 1; 처럼 쓰기를 시도하면:
- CPU는 메모리에 접근하려고 한다.
- 그런데 페이지 테이블을 보니, 아직 물리 메모리 매핑이 안 되어 있지 않았다.
- 그러면 CPU가 Page Fault 예외(Page Fault Exception)를 발생시킨다.
운영체제(OS)는 이 Page Fault를 잡아 처리한다.
3. 운영체제의 Page Fault 처리 과정
운영체제는 다음 순서로 처리한다:
- Fault가 발생한 주소를 확인한다.
- 페이지 테이블을 보고, 이 Fault가 Demand-zero 페이지에 대한 것임을 안다.
- 새로운 물리 메모리 페이지 하나를 할당한다.
- 그 페이지를 모두 0으로 초기화한다. (보안을 위해 무조건 0으로 설정한다.)
- 이 새 페이지를 가상 주소에 매핑한다.
- 페이지 테이블을 업데이트한다.
- 페이지의 존재(bit set)
- 읽기/쓰기 권한(bit set)
- 프로그램이 다시 정상적으로 해당 메모리에 접근할 수 있도록 한다.
결국 프로그램은 아무것도 모르는 상태로 big_array[0] = 1 같은 코드를 수행하게 된다.
4. 메모리 초기화가 꼭 필요한 이유
- 보안상 필요하다.
(만약 초기화를 안 하면, 다른 프로세스가 쓰던 메모리 내용을 읽어버릴 수도 있다.) - 따라서 OS는 항상 새로 할당된 demand-zero 메모리를 "0으로 초기화" 하고, 사용자 프로그램에 제공한다.
Demand-Zero vs Copy-On-Write
구부 | Demand-Zero | Copy-On-Write (COW) |
발생 조건 | 처음 메모리 접근할 때 (아직 물리 메모리 없음) | 공유된 페이지를 수정하려고 할 때 (다른 프로세스와 공유 중) |
초기 상태 | "메모리를 요청했지만, 실제로 0으로 초기화된 물리 페이지는 아직 없음" | "다른 프로세스와 물리 페이지를 공유 중" |
Fault 종류 | Demand-Zero Page Fault | Copy-On-Write Page Fault |
OS 대응 | 새 물리 페이지를 할당하고 0으로 초기화 | 새 물리 페이지를 할당하고 기존 데이터를 복사 |
사용 예시 | calloc(), BSS 섹션, MAP_ANONYMOUS | fork() 이후 부모-자식 프로세스 메모리 분리 |
1. Demand-Zero: "아예 메모리가 없던 상태"
- 메모리 요청했지만 물리 메모리 할당이 미뤄진 상태.
- 접근할 때 0으로 초기화된 페이지를 새로 만들어서 제공.
- 특징: 새로 할당 + 0으로 초기화
int *arr = calloc(1000, sizeof(int));
- 여기서는 메모리를 쓰기 전까지 진짜 물리 메모리가 없음.
- 쓰려고 할 때 Page Fault → OS가 0으로 초기화된 페이지를 연결해줌
2. Copy-On-Write: "공유된 메모리를 복사할 때"
- 원래 물리 메모리가 존재하고, 여러 프로세스가 같은 물리 메모리를 공유하고 있다.
- 누군가가 이 공유 메모리를 수정하려고 하면 Page Fault 발생.
- OS는 수정하려는 프로세스만 새로운 복사본을 만들고, 기존 데이터 복사 후 수정하게 한다.
- 특징: 복사 + 수정 (읽기만 하면 복사 안 함)
pid_t pid = fork();
- fork() 호출하면 부모 프로세스의 메모리를 자식이 그대로 공유한다.
- 둘 다 같은 물리 페이지를 읽기는 자유롭게 함.
- 하지만 자식이나 부모가 수정(write) 하려고 하면
- COW Page Fault
- OS가 새 페이지를 복사해 주고, 그 뒤 수정하게 한다.
'크래프톤 정글' 카테고리의 다른 글
[CS] 이더넷(Ethernet) (2) | 2025.04.28 |
---|---|
[CS] DMA(Direct Memory Access) (0) | 2025.04.28 |
RB-Tree 구현 회고 - 실패하면 디버그 성공하면 리눅스 아닙니까! (0) | 2025.04.23 |
AVL 트리 개념 정리 (0) | 2025.04.22 |
RB-Tree 구현하기 (C언어) - Part.6 삭제 구현 (0) | 2025.04.22 |