[C언어/말록랩] calloc이 malloc과 memset 조합보다 압도적으로 빠른 가상 메모리 Zero Page 공유와 CoW(Copy-on-Write) 지연 할당 원리

자신감·어제

6주차

목록 보기
7/7

소주제

  1. DRAM 물리 셀의 전하 상태와 운영체제 커널의 프로세스 간 정보 유출 차단용 Zero-out 보안 규약
  2. malloc과 memset 조합 실행 시 CPU 명령어(rep stosq / SIMD), 페이지 폴트 연쇄 발생과 캐시 스래싱(Cache Thrashing) 메커니즘
  3. calloc의 가상 메모리 최적화: x86-64 PTE 구조(PFN, Present, R/W, Dirty)와 커널 ZERO_PAGE CoW(Copy-on-Write) 지연 할당 원리
  4. 컴파일/링크 타임 바이너리 구조와 런타임 힙 할당: 실행 파일 ELF(.bss vs .data)와 calloc의 물리 메모리 절약 차이
  5. 메모리 공급 출처에 따른 성능 분기: 대형 할당(mmap 시스템 콜) vs 소형 할당(힙 가용 리스트, 경계 태그 및 Dirty 청크 오버헤드)
  6. 상위 소프트웨어 레벨의 초기화 최적화: 세대 번호 기반 타임스탬프(Epoch) 기법의 O(1) 논리적 리셋과 메모리 추상화 계층 구분
  7. 프로젝트 로드맵 연계: 사용자 공간 말록랩(Malloc Lab)에서 커널 공간 핀토스(Pintos Project 3 가상 메모리)까지의 아키텍처 관통

1. DRAM 물리 셀의 전하 상태와 운영체제 커널의 프로세스 간 정보 유출 차단용 Zero-out 보안 규약

1.1 DRAM 반도체 소자의 물리적 상태

컴퓨터의 주기억장치(DRAM)는 1비트마다 트랜지스터 1개와 커패시터 1개로 구성된 미세 물리 셀들의 집합체입니다.

  • 커패시터에 전하가 충전되어 있으면 1, 방전되어 있으면 0의 전압 신호로 판독됩니다.
  • 전원이 공급되는 동안 컴퓨터 하드웨어 내부에는 비어 있는 상태라는 개념이 물리적으로 존재하지 않으며, 모든 번지수에는 0 또는 1의 전압 상태가 항시 잔존합니다.

1.2 프로세스 간 메모리 공유와 정보 유출(Information Leak) 방지

운영체제(OS)는 한정된 물리 RAM을 여러 프로세스가 번갈아 할당받고 해제(free)하도록 중계합니다.

  • 프로세스 A가 실행을 마치거나 동적 메모리를 해제했을 때, 해당 물리 메모리 셀들에는 프로세스 A가 다루던 암호화 키, 로그인 세션 토큰, 개인 식별 데이터가 물리적 비트 형태로 그대로 잔존합니다.
  • 만약 커널이 이 물리 메모리를 0으로 초기화하지 않은 채 프로세스 B에게 할당하면, 프로세스 B는 포인터 역참조를 통해 프로세스 A의 기밀 데이터를 메모리 덤프로 탈취할 수 있는 보안 취약점이 발생합니다.
  • 따라서 모든 현대 운영체제 커널은 "유저 모드 프로세스에게 새로운 물리 메모리 페이지를 할당할 때는, 반드시 커널 모드에서 모든 바이트를 0으로 덮어써서(Zero-out) 전달해야 한다"는 하드웨어 및 운영체제 보안 불변식을 강제합니다.

2. malloc과 memset 조합 실행 시 CPU 명령어(rep stosq / SIMD), 페이지 폴트 연쇄 발생과 캐시 스래싱(Cache Thrashing) 메커니즘

0으로 초기화된 대형 메모리를 확보하기 위해 malloc 직후 memset을 수행하는 방식은 하드웨어 자원을 극심하게 낭비합니다.

void *ptr = malloc(1024 * 1024 * 100); // 100MB 가상 메모리 할당
memset(ptr, 0, 1024 * 1024 * 100);     // 100MB 전체에 물리적 0 쓰기 루프 실행

2.1 저수준 명령어 실행: rep stosq 및 SIMD 레지스터

  • 컴파일러와 C 라이브러리의 memset 함수는 x86-64 아키텍처에서 고속 반복 명령어인 rep stosq 또는 128비트/256비트 SIMD(AVX) 벡터 레지스터를 호출하도록 어셈블리 수준에서 최적화되어 있습니다.
  • 이는 CPU 코어가 메모리 버스의 최대 대역폭을 점유하며 순차적으로 물리 주소 공간에 0을 강제 기록하는 하드웨어 동작입니다.

2.2 지연 할당 무력화와 연쇄적 페이지 폴트(Page Fault)

  • malloc 호출 시점에는 운영체제가 가상 주소 공간(VMA, Virtual Memory Area)의 연속된 주소 범위만 예약할 뿐, 실제 물리 RAM 프레임을 전혀 연결하지 않습니다.
  • 그러나 직후 실행되는 memset 루프는 할당받은 영역의 첫 1바이트부터 마지막 바이트까지 모든 페이지(4KB 단위)에 순차 쓰기를 시도합니다.
  • 이로 인해 운영체제의 지연 할당(Lazy Allocation) 최적화가 전면 무력화되며, 100MB 할당 기준 총 25,600회(100MB / 4KB)에 달하는 하드웨어 인터럽트(Page Fault)가 연쇄적으로 발생합니다.
  • CPU 제어권이 유저 모드와 커널 모드를 25,600번 오가며 문맥 교환 오버헤드와 물리 프레임 할당 연산이 즉각 강제됩니다.

2.3 이중 0 쓰기(Double Zeroing)와 캐시 스래싱(Cache Thrashing)

  1. 이중 0 쓰기 오버헤드:
    • 커널은 보안 규약에 따라 새 물리 프레임을 할당할 때마다 커널 내부에서 이미 4KB 전체를 0으로 밀어버립니다(1차 0 쓰기).
    • 유저 공간으로 복귀한 직후, memset 루프가 동일한 물리 메모리에 다시 0을 쓰는 중복 명령을 수행합니다(2차 0 쓰기).
    • 동일한 물리 셀에 0을 두 번 연속 기록하는 물리 버스 낭비가 발생합니다.
  2. 캐시 스래싱 (Cache Thrashing):
    • CPU가 대규모 메모리 영역에 순차적으로 0 데이터를 쏟아붓는 동안, CPU 내부의 초고속 SRAM인 L1, L2, L3 캐시 라인이 전부 0 데이터로 가득 찹니다.
    • 이 과정에서 애플리케이션의 핵심 코드와 실제 작업 데이터가 캐시에서 강제 방출(Eviction)되어, 시스템 전체의 캐시 적중률(Cache Hit Ratio)이 급락합니다.

3. calloc의 가상 메모리 최적화: x86-64 PTE 구조(PFN, Present, R/W, Dirty)와 커널 ZERO_PAGE CoW(Copy-on-Write) 지연 할당 원리

calloc은 메모리 요청 시점의 실제 물리 메모리 기록을 생략하고, MMU(Memory Management Unit)와 페이징 하드웨어를 제어하여 할당 속도를 상수 시간 O(1)로 단축합니다.

3.1 64비트 x86-64 페이지 테이블 엔트리(PTE) 구조

가상 주소를 물리 주소로 변환하기 위해 프로세스마다 존재하는 다단계 페이지 테이블의 최하위 행(Entry)을 PTE(Page Table Entry)라고 부르며, 8바이트(64비트) 크기를 갖습니다.

비트 필드명칭기능 및 상태
Bit 0Present (P)1: 물리 RAM에 프레임 존재 / 0: 미할당 또는 스왑 디스크 상태 (접근 시 Page Fault 유발)
Bit 1Read/Write (R/W)1: 읽기 및 쓰기 모두 허용 / 0: 읽기 전용 (쓰기 시도 시 Page Fault 유발)
Bit 2User/Supervisor (U/S)1: 사용자 모드 접근 허용 / 0: 커널 모드 전용 접근
Bit 5Accessed (A)해당 페이지의 읽기/쓰기 참조 발생 시 하드웨어가 1로 설정 (페이지 교체 시 참조)
Bit 6Dirty (D)해당 페이지에 쓰기 연산 발생 시 하드웨어가 1로 설정 (스왑 동기화 판단)
Bit 12~51PFN (Page Frame Number)매핑된 실제 물리 RAM 프레임의 4KB 단위 물리 기준 주소 비트열

3.2 커널 단일 ZERO_PAGE의 읽기 전용 공유

운영체제 커널은 부팅 시 모든 바이트가 0으로 채워진 단 하나의 물리 4KB 페이지 프레임인 ZERO_PAGE를 물리 RAM에 상주시켜 둡니다.

[프로세스 가상 메모리 공간]                    [물리 RAM]
가상 페이지 0 (0x1000) ──┐
가상 페이지 1 (0x2000) ──┼──(PTE: Present=1, R/W=0)──▶ [물리 ZERO_PAGE (4KB 단일 프레임)]
가상 페이지 2 (0x3000) ──┘
  • calloc으로 100MB(25,600개 페이지)를 요청하면, 커널은 25,600개의 가상 페이지 전체가 이 단 하나의 물리 ZERO_PAGE를 가리키도록 페이지 테이블의 PFN을 매핑합니다.
  • 이때 PTE의 R/W 비트는 0(읽기 전용)으로 설정됩니다.
  • 소비되는 실제 물리 메모리는 단 4KB이며, CPU가 메모리에 0을 기록하는 루프는 단 한 번도 실행되지 않으므로 할당 연산이 즉각 완료됩니다.

3.3 CoW(Copy-on-Write) 하드웨어 발동 상세 메커니즘

프로세스가 할당받은 주소 공간을 읽기(Read)만 할 때는 수만 개의 가상 페이지가 단 하나의 물리 ZERO_PAGE를 공유하며 항상 0을 읽어옵니다.

실제 쓰기(Write) 연산이 발생하는 순간의 하드웨어 및 커널 제어 흐름은 다음과 같습니다.

1. 프로그램: 특정 가상 주소에 데이터 쓰기(Write) 명령어 실행
   │
2. CPU MMU: 페이지 테이블 조회 ──▶ PTE의 R/W 비트가 0(읽기 전용)임을 감지
   │
3. 하드웨어 인터럽트: CPU가 #PF (Page Fault 인터럽트 벡터 14) 발생
   │
4. 제어권 이관: 커널의 Page Fault 핸들러로 전환
   │
5. 예외 원인 판별: 핸들러가 VMA를 검사하여 정당한 쓰기 영역(CoW 대상)인지 불법 주소(Segmentation Fault)인지 확인
   │
6. 물리 프레임 분리: 커널이 빈 물리 메모리에서 새 4KB 프레임 1장을 즉각 할당
   │
7. 데이터 복제: 기존 ZERO_PAGE의 내용(4KB의 0)을 새로 할당된 물리 프레임으로 1회 복사
   │
8. PTE 재설정: 해당 가상 페이지의 PFN을 새 물리 프레임 주소로 교체하고, R/W 비트를 1(쓰기 허용)로 갱신
   │
9. 복귀 및 재실행: Page Fault 핸들러 종료 후, CPU가 중단되었던 쓰기 명령어를 정상 재실행
  • 희소 접근(Sparse Access) 최적화: 100MB를 할당받고 실제로는 특정 위치 4KB 페이지만 수정하는 경우, malloc + memset은 100MB 전체에 물리 RAM을 강제 할당하고 2회 0 쓰기를 수행하지만, calloc은 수정된 단 4KB 페이지만 물리 프레임을 분리하고 나머지 99.996MB에 대해서는 물리 메모리 소모와 쓰기 연산이 0으로 유지됩니다.

4. 컴파일/링크 타임 바이너리 구조와 런타임 힙 할당: 실행 파일 ELF(.bss vs .data)와 calloc의 물리 메모리 절약 차이

'0으로 초기화된 메모리가 디스크 또는 RAM 공간을 차지하지 않는다'는 개념은 컴파일/링크 타임의 정적 바이너리 구조와 런타임 운영체제 가상 메모리 관리의 차이에서 비롯됩니다.

+--------------------------------------------------+
|                    ELF 실행 파일                  |
|  +--------------------------------------------+  |
|  | .text 섹션: 컴파일된 기계어 코드            |  |
|  +--------------------------------------------+  |
|  | .data 섹션: 초기화된 전역/정적 변수         |  | ◀── 실제 디스크 용량 차지 (초기화 데이터 기록)
|  +--------------------------------------------+  |
|  | .bss 섹션:  0 또는 미초기화 전역 변수       |  | ◀── 메타데이터(크기 정보)만 기록 (용량 차지 0)
|  +--------------------------------------------+  |
+--------------------------------------------------+

4.1 정적 데이터 섹션: .data vs .bss

  • .data 섹션: int arr[1000] = {1, 2, ...};처럼 0이 아닌 유의미한 값으로 초기화된 전역 변수입니다. 초기화된 실제 바이트 데이터가 실행 파일(바이너리) 내부에 물리적으로 기록되므로 파일의 디스크 용량을 직접 차지합니다.
  • .bss 섹션: int arr[1000] = {0};처럼 0으로 초기화되었거나 초기화되지 않은 전역 변수입니다. 컴파일러는 4000바이트의 0을 파일에 기록하지 않고, "프로그램 적재 시 4000바이트 크기의 0 공간이 필요함"이라는 메타데이터(크기 정보)만 기록합니다. 따라서 실행 파일의 디스크 크기가 늘어나지 않습니다.

4.2 .bss 섹션과 calloc의 핵심 차이점

  • .bss (정적 전역 변수): 컴파일 및 링크 타임 최적화입니다. 하드디스크의 실행 파일 크기를 절약하는 것이 목적이며, 프로그램 실행 시 운영체제 로더가 메모리에 적재하면서 가상 메모리에 매핑합니다.
  • calloc (동적 힙 할당): 런타임(Runtime) OS 가상 메모리 최적화입니다. 컴파일러는 실행 시점에 calloc에 어떤 크기가 들어올지 알 수 없으므로 단순히 함수 호출 코드(call calloc)만 생성합니다. 실제 메모리 매핑과 ZERO_PAGE 공유, CoW 처리는 100% 실행 중에 운영체제 커널에 의해 수행되어 물리 RAM 용량을 절약합니다.

5. 메모리 공급 출처에 따른 성능 분기: 대형 할당(mmap 시스템 콜) vs 소형 할당(힙 가용 리스트, 경계 태그 및 Dirty 청크 오버헤드)

calloc의 Zero Page CoW 최적화는 모든 크기의 할당에 일괄 적용되지 않으며, 할당기가 메모리를 가져오는 공급 경로에 따라 물리적 동작이 분기됩니다.

비교 항목대형 할당 (Large Allocation)소형 할당 (Small Allocation)
기준 크기glibc 기준 대략 128KB 이상 (MMAP_THRESHOLD)수 바이트 ~ 수십 KB 단위
기저 메커니즘커널 mmap 시스템 콜 직접 호출사용자 공간 힙 내부 가용 리스트(Free List) 탐색 및 분할
메모리 상태OS가 새로 매핑한 Clean(0 보장) 페이지이전에 프로세스가 쓰다 해제한 Dirty(쓰레기 값 잔존) 블록
calloc 내부 동작커널의 0 보장을 신뢰하여 유저 레벨 0 쓰기 전면 생략기존 잔존 데이터를 지우기 위해 내부에서 직접 memset 루프 실행
속도 차이Zero Page 공유로 calloc이 수십~수백 배 압도적으로 빠름내부에서 memset을 돌리므로 calloc과 malloc + memset의 속도가 기계적으로 동일

5.1 대형 할당: mmap 시스템 콜

  • 요청 크기가 MMAP_THRESHOLD(기본 128KB) 이상이면, 힙 영역(brk)을 확장하지 않고 커널의 mmap 시스템 콜을 통해 독립된 익명 페이지(Anonymous Page)를 매핑받습니다.
  • 커널이 새로 제공하는 페이지는 앞서 설명한 커널 보안 규약에 의해 0 초기화가 보장되므로, calloc은 별도의 바이트 쓰기를 전혀 하지 않고 Zero Page와 CoW를 적용합니다.

5.2 소형 할당: 가용 리스트(Free List)와 Dirty 청크

  • 잦은 소형 할당마다 시스템 콜을 호출하면 문맥 교환 오버헤드로 인해 시스템 성능이 저하됩니다.
  • 따라서 할당기는 과거에 free되어 보관 중인 가용 블록(Free Block)을 쪼개어 재할당합니다.
  • 이 블록 내부에는 이전에 프로그램이 기록했던 정수, 문자열, 포인터 등의 과거 데이터(Dirty Data)가 그대로 남아 있습니다.
  • 이는 OS 커널이 새로 매핑해 준 페이지가 아니므로 Zero Page 메커니즘을 적용할 수 없습니다.
  • 따라서 calloc 라이브러리 함수 역시 사용자에게 반환하기 전에 자체 루프를 돌아 블록 페이로드를 바이트 단위로 0으로 덮어써야(memset) 합니다.

5.3 힙 블록 메타데이터 구조: 경계 태그(Boundary Tag)와 단편화

말록랩에서 구현하는 동적 메모리 할당기의 힙 블록은 다음과 같은 구조로 동작합니다.

[할당 블록 메모리 구조]               [가용 블록(Free Block) 메모리 구조]
┌───────────────────────────┐         ┌───────────────────────────┐
│ Header (크기 + 할당 비트 1)  │         │ Header (크기 + 할당 비트 0)  │
├───────────────────────────┤         ├───────────────────────────┤
│                           │         │ NEXT 가용 포인터 (8바이트) │ ──▶ 다음 가용 블록 주소
│ User Payload 데이터 영역    │         ├───────────────────────────┤
│                           │         │ PREV 가용 포인터 (8바이트) │ ◀── 이전 가용 블록 주소
│                           │         ├───────────────────────────┤
│                           │         │ 미사용 여백 공간            │
├───────────────────────────┤         ├───────────────────────────┤
│ Footer (크기 + 할당 비트 1)  │         │ Footer (크기 + 할당 비트 0)  │
└───────────────────────────┘         └───────────────────────────┘
  1. 헤더(Header)와 푸터(Footer) 경계 태그:
    • 블록의 양 끝에 위치하는 4바이트 또는 8바이트 메타데이터입니다.
    • 블록의 전체 크기(Size)와 할당 여부(Allocated Bit, 최하위 비트 a/f)를 비트 패킹으로 저장합니다.
    • 현재 블록 직전의 푸터를 읽어 이전 블록의 가용 여부를 즉시 확인하므로, 인접 가용 블록과의 병합(Coalescing)을 상수 시간 O(1)에 수행합니다.
  2. Explicit Free List의 포인터 오버레이(Overlay):
    • 가용 블록들을 이중 연결 리스트로 연결할 때, 별도의 추가 메모리를 동적 할당하지 않습니다.
    • 블록이 free 상태일 때는 사용자의 페이로드가 비어 있으므로, 페이로드의 첫 16바이트 공간에 NEXT와 PREV 포인터를 직접 덮어씁니다(Overlay).
  3. 단편화(Fragmentation):
    • 내부 단편화(Internal Fragmentation): 하드웨어 정렬 규약(8바이트 또는 16바이트)과 헤더/푸터 메타데이터로 인해 사용자가 요청한 크기보다 큰 블록이 할당되어 낭비되는 바이트 공간입니다.
    • 외부 단편화(External Fragmentation): 가용 메모리의 총합은 요청 크기보다 크지만, 가용 블록들이 작은 조각들로 분할되어 있어 단일 연속 공간을 할당할 수 없는 상태입니다.

6. 상위 소프트웨어 레벨의 초기화 최적화: 세대 번호 기반 타임스탬프(Epoch) 기법의 O(1) 논리적 리셋과 메모리 추상화 계층 구분

물리 메모리의 전압이나 OS 가상 메모리 조작과 무관하게, 배열이나 테이블 자료구조의 논리적 초기화 비용을 항상 상수 시간 O(1)로 유지하는 소프트웨어 알고리즘 기법이 존재합니다.

6.1 동작 원리 및 C 구현 코드

데이터를 저장하는 각 슬롯에 실제 값과 함께 해당 데이터가 기록된 세대 번호(generation)를 구조체로 묶어 관리합니다. 시스템 전역에는 단 하나의 정수 카운터인 global_epoch를 유지합니다.

#include <stdio.h>
#include <stdint.h>

#define MAX_SIZE 1000000

typedef struct {
    int value;
    uint32_t generation;
} Slot;

Slot table[MAX_SIZE];
uint32_t global_epoch = 1;

// O(1) 논리적 초기화 연산
void clear_table(void) {
    global_epoch++; // 수백만 개 요소를 0으로 미는 루프 없이 카운터 1 증가로 전체 초기화
}

// 읽기 연산: 세대 번호 일치 여부 판별
int read_slot(int index) {
    if (table[index].generation != global_epoch) {
        return 0; // 현재 유효 세대의 값이 아니므로 초기화된 상태(0)로 취급
    }
    return table[index].value;
}

// 쓰기 연산: 현재 세대 번호를 각인
void write_slot(int index, int val) {
    table[index].value = val;
    table[index].generation = global_epoch; // 최신 세대 기록
}

6.2 특징 및 계층(Layer) 구분

  1. 장점과 한계:
    • 배열의 크기가 수억 개에 달해도 clear_table() 호출 시 루프 순회 없이 단 한 번의 정수 덧셈으로 즉각 리셋이 완료됩니다.
    • 단, 슬롯마다 4바이트의 generation 필드를 추가로 유지해야 하므로 메모리 사용량이 증가하며, 32비트 정수 오버플로우 발생 시의 리셋 처리가 요구됩니다.
  2. 추상화 계층의 본질적 차이:
    • 타임스탬프(Epoch) 기법은 애플리케이션 레벨에서 논리적 유효성만을 판별하는 소프트웨어 알고리즘 기법입니다.
    • 반면 calloc의 Zero Page 매핑과 말록랩/OS 커널의 메모리 관리는 하드웨어 MMU, DRAM 물리 셀, 바이트 단위 주소 버스, 페이지 테이블 비트를 직접 제어하는 물리 및 시스템 계층 기법입니다.

7. 프로젝트 로드맵 연계: 사용자 공간 말록랩(Malloc Lab)에서 커널 공간 핀토스(Pintos Project 3 가상 메모리)까지의 아키텍처 관통

컴퓨터 시스템의 메모리 관리 아키텍처는 유저 레벨과 커널 레벨로 명확히 분리되며, 말록랩과 핀토스는 이 거대한 구조의 상부와 하부를 각각 직접 구현하는 과정입니다.

[사용자 공간 (User Space)]
  │  애플리케이션 프로그램 코드 (User Application)
  │  C 표준 라이브러리 (malloc, calloc, realloc, free)
  │
  └─▶ [6주차 말록랩 (Malloc Lab)]: 사용자 레벨 힙 할당기 직접 구현
        - mem_sbrk로 연속된 가상 힙 메모리 공간 확보
        - 헤더/푸터 경계 태그(Boundary Tag) 비트 연산
        - Explicit Free List 관리 (페이로드 포인터 오버레이)
        - 가용 블록 탐색(First-fit / Next-fit / Best-fit) 및 분할(place)
        - 상수 시간 인접 가용 블록 병합(Coalescing) 및 단편화 제어

──────────────── 시스템 콜 경계 (Syscall Interface: brk, mmap) ────────────────

[커널 공간 (Kernel Space)]
  │
  └─▶ [7주차 핀토스 (Pintos Project 3: Virtual Memory)]: OS 커널 메모리 서브시스템 직접 구현
        - 하드웨어 다단계 페이지 테이블(Page Table) 및 64비트 PTE 비트 직접 조작
        - CPU 하드웨어 인터럽트 #PF를 수신하는 Page Fault 핸들러 구현
        - 익명 페이지(Anonymous Page) 지연 할당(Lazy Allocation)
        - Frame Table을 통한 물리 RAM 프레임 점유 관리
        - 물리 RAM 부족 시 페이지 교체(Clock 알고리즘, Eviction) 수행
        - 스왑 디스크(Swap Table) 읽기/쓰기 및 파일 매핑(Memory-Mapped Files) 구현

7.1 말록랩(Malloc Lab)과 mm_calloc

  • 말록랩에서 구현하는 할당기는 OS가 이미 가상 메모리를 매핑해 주었다는 전제하에 작동합니다.
  • mm_calloc 구현 시 학생 레벨 할당기가 다음과 같이 작성되는 이유가 바로 메모리 출처가 유저 힙 가용 리스트이기 때문입니다.
void *mm_calloc(size_t nmemb, size_t size) {
    size_t total_size = nmemb * size;
    void *ptr = mm_malloc(total_size);
    if (ptr != NULL) {
        memset(ptr, 0, total_size); // 힙 가용 블록 재사용이므로 사용자 레벨 memset 필수
    }
    return ptr;
}

7.2 7주차 핀토스(Pintos) 커널의 palloc_get_page(PAL_ZERO) 연계

  • 7주차 핀토스 커널의 페이지 할당자(threads/palloc.c) 역시 플래그를 통해 0 초기화 여부를 하드웨어 수준에서 제어합니다.
  • palloc_get_page(PAL_ZERO) 호출 시, 커널은 물리 4KB 페이지 프레임을 할당한 직후 커널 모드에서 memset(page, 0, PGSIZE)를 직접 실행하여 0으로 초기화한 뒤 반환합니다.
  • PAL_ZERO 플래그가 없으면 0 초기화 연산을 건너뛰어 페이지 할당 지연을 최소화합니다.

7.3 시스템 요약

  • calloc이 malloc + memset보다 압도적으로 빠른 이유는 CPU의 물리적 0 쓰기 루프를 커널의 단일 ZERO_PAGE 매핑과 CoW 지연 할당이라는 하드웨어 페이징 메커니즘으로 대체했기 때문입니다.
  • 이 원리는 사용자 레벨 힙 메모리 관리자(6주차 말록랩)의 포인터 제어부터, 시스템 콜 경계를 넘어 운영체제 커널(7주차 핀토스 가상 메모리)의 페이지 테이블 및 인터럽트 핸들러 설계로 이어지는 컴퓨터 시스템의 핵심 동작 원리입니다.
profile
잘할 수밖에 없는 자신감

0개의 댓글