CSAPP 9장 | 세그먼트와 힙: malloc이 메모리를 관리하는 방법

맹쥐·2025년 4월 28일

정글-개발일지

목록 보기
20/24
post-thumbnail

페이지를 이해했다면,
이제 세그먼트(Segment) 개념도 자연스럽게 받아들일 수 있다.

참고자료 🌼
CSAPP 9장 | 가상 주소 → 물리 주소 변환
[손필기] PPN, PTE, VPO | 가상주소 → 물리주소 변환


세그먼트(Segment)란

  • 프로그램을 의미 있는 논리적 구역 단위로 나눈 것이다.

쉽게말하면, 데이터를 단순히 " 크기 "로 쪼갠 것이 페이지이고,
데이터를 "의미/역할"에 따라 나눈 것이 세그먼트다.

정글 캠퍼스에서 예를 들자면.

  • 세그먼트 - 목적별로 나눈 큰 구역
    게임랩 / 테크랩 / 정글랩 처럼 "역할"에 따라 분리한 구역이다.
  • 페이지 - 균일하게 쪼갠 작은 덩어리
    한 반에서 3명씩 "크기"를 맞춰 조를 나눈 것처럼.

따라서 세그먼트는 페이지보다 더 큰 의미 단위로 볼 수 있다.


세그먼트는 예전에는 메모리 보호와 논리적 구조화를 위해 자주 사용됐지만,
현대 OS에서는 페이징을 기본으로 하고 세그먼트는 최소화하는 경우가 많다고 한다.

하지만 여전히 "코드 영역", "데이터 영역", "스택 영역" 등은
프로그램이 구동될 때 논리적 세그먼트로 나눠서 관리한다.

실제로 OS에서 세그먼트와 페이지가 어떻게 구성되어 있는지 살펴보자.


실제 운영체제(OS)에서 세그먼트와 페이지는 어떻게 구성될까?

현대 운영체제에서는 "세그먼트 + 페이지" 방식을 같이 사용한다.

1️⃣ 프로그램이 실행되면? (메모리에 올라갈 때)

운영체제는 프로그램을 크게 논리적 세그먼트로 나눈다.

세그먼트 종류역할
코드(Code)프로그램 명령어 (기계어) 저장
데이터(Data)전역 변수, static 변수 저장
힙(Heap)동적 메모리 할당 영역 (malloc 등)
스택(Stack)함수 호출 시 생성되는 지역 변수 등

2️⃣ 각 세그먼트는 다시 '페이지'로 쪼개진다

운영체제는 이 세그먼트들을 실제 메모리에 올릴 때
고정 크기(4KB 등)의 페이지로 쪼갠다.

"논리적으로 세그먼트 → 물리적으로 페이지" 구조라고 보면 된다!

단계설명
논리적 구분세그먼트 (코드, 데이터, 스택, 힙)
실제 메모리 배치고정 크기(4KB) 페이지로 쪼개서 관리

세그먼트 → 힙 메모리 구조로
앞서 살펴봤듯이,
운영체제는 프로그램을 논리적으로 세그먼트 단위로 나누어 관리한다.

그중에서도 우리는 특히 힙(Heap)이라는 영역에 주목해야 한다.

힙(Heap) 영역이란?

프로그램 실행 중에 필요할 때마다 메모리를 "동적으로" 할당받기 위해 사용되는 메모리 구역이다.

쉽게 말하면, 프로그램이 처음부터 "나는 무조건 1GB 쓸거야!" 이렇게 예약하는 게 아니라
필요한 만큼만 요청해서 쓰고,
다 쓰면 반납
하는 방식이다.

필요할 때 malloc() 같은 함수를 통해 메모리를 빌려쓰고,
다 쓴 후에는 free()를 통해 반납하는 것이다.

✅ 전역 변수는 데이터 세그먼트에,
✅ 지역 변수는 스택 세그먼트에 저장되지만,
✅ malloc()으로 만든 메모리는 힙 세그먼트에 저장된다.

힙 메모리의 특징

  • 런타임(실행 중)에 메모리를 요청한다. (동적 할당)
  • 사용자는 malloc(), free() 같은 함수를 통해 메모리를 직접 관리한다.
  • 메모리 공간은 낮은 주소에서 높은 주소 방향으로 성장한다.

💬 참고: 스택(stack)은 반대로 높은 주소 → 낮은 주소로 자라난다.
그래서 둘이 충돌하지 않도록 설계가 필요하다!


그렇다면 힙이 메모리를 실제로 어떻게 할당할까?
가장 기본적으로 사용하는 함수가 있다.

1. malloc() 호출

  1. 프로그램이 malloc(size)로 메모리를 요청하면,
  2. 내부 힙 관리자가 "free block 목록"을 뒤진다.
  3. 요청한 크기에 딱 맞거나 충분히 큰 빈 블록을 찾아서 준다.

❗️ 이때 heap이 부족하면 어떻게 할까?

👉 heap 확장 - sbrk() 시스템 콜

heap에 빈 공간이 없으면, 운영체제(OS) 에게 새로운 메모리를 요청한다.
이때 사용하는 게 바로 sbrk(size) 시스템 콜이다.

sbrk()는 운영체제에게 "힙(heap) 끝주소를 size만큼 늘려주세요!"라고 요청하는 함수다.
프로그램이 직접 메모리를 늘리는 게 아니라, 운영체제에 공식적으로 부탁하는 거다.

운영체제는 최종 보스다.
사용자 프로그램이 운영체제까지 가서 무언가를 요청하는 순간,
우리는 이를 "시스템 콜(System Call)" 이라고 부른다.

시스템콜 참고자료 🌼
CSAPP 8장 | 예외는 어떻게 정의되고, 어떻게 처리될까?
CSAPP 8장 번외편 | 운영체제, 커널, CPU, 시스템 콜 정리


2. free() 호출

  1. 사용이 끝난 메모리를 free(ptr) 호출
  2. 해당 블록을 "free block" 으로 표시
  3. 주변에 있는 다른 free block이 있다면 병합(coalescing) 해서 크기를 키운다.

마무리 정리

mallocfree는 단순히 메모리를 빌려쓰고 반납하는 것처럼 보이지만,
내부에서는 heap 공간을 관리하고, 필요할 때는 운영체제에 시스템 콜을 통해 메모리를 요청하는 치밀한 관리가 이루어진다.

profile
이유민

0개의 댓글