포스트

[OS] 프로세스 메모리 구조

1. 주소 공간

1.1. CPU address space

  • 물리 메모리 (주소) 라고도 한다.
  • CPU Bus 크기1에 의해 결정된다.
    • 32 bit CPU → 주소선 32개 → $2^{32}$ → 4GB
    • 64 bit CPU → 주소선 64개 → $2^{64}$ → 16EB(=2,305,843.01TB)
  • 주소 공간은 0번지부터 시작한다.
  • 1개 번지의 저장공간 크기 $=$ 1바이트
  • CPU 주소공간보다 큰 메모리 엑세스 불가능
  • CPU 주소공간보다 작은 양의 메모리는 가능
    • 예) 32비트 CPU 가진 컴퓨터에 2GB 메모리 설치되어 있을 때 → 2GB 넘어서 액세스하면 오류 발생

1.2. Process address space

  • 프로세스가 실행되는 중 접근이 허용된 주소의 최대 범위 $=$ Segmentation
    • 할당된 공간에 대한 경계 레지스터, 한계 레지스터 벗어나는지 감시 (CPU 관점)

그런데 프로세스는 자신이 CPU 주소 공간 전체를 독점하는 것처럼 보인다!

  • 가상 메모리‘라는 개념이 적용되기 때문이다.
  • 모든 프로세스는 자신만의 가상 주소 공간을 가진다.
    • 32bit CPU에서 작동되는 프로세스는 논리적으로 4GB 메모리 할당받은 것처럼 보인다.(물리 메모리가 2GB더라도)

→ Logical memory vs Physical memory

  • 프로세스 주소 공간은 두 부분(User space, Kernel space)으로 나누어진다.

1.2.1. User space(사용자 공간)

  • 코드 영역
  • 데이터 영역
  • 힙 영역
  • 스택 영역

1.2.2. Kernel space(커널 공간)

프로세스가 syscall 통해 이용하는 공간으로, 모든 사용자 프로세스에 의해 공유된다.

  • 커널 코드
  • 커널 데이터
  • 커널 스택(커널 코드가 실행될 때)

2. 가상 메모리 사용 이유

  • 메모리 확장성
    • 물리적 메모리는 한정적이지만, 가상 메모리는 더 큰 공간으로 구성 가능
    • 초과 분은 보조기억장치 등을 활용, 가상 주소 공간은 저장장치 구분 없이 하나의 가상 공간으로 활용이 가능하다. → Page swap 등 필요
  • 모든 프로그램에 대한 동일한 메모리 공간 제공
    • 각 프로세스는 다른 프로세스 신경 쓸 필요가 X
    • 각 프로세스 간 Memory protection → 메모리 격리, 보호

RTOS 등 일부 OS는 가상 메모리 이용하지 않고 직접 접근하기도 한다.

3. 프로세스의 메모리 구조

프로세스가 메모리에 올라갈 때, OS는 특정한 구조로 메모리에 적재시킨다. 이때 영역을 구분하는데, 크게 네 부분으로 구분할 수 있다.

영역할당되는 객체크기 결정 시기설명
코드(code) 영역프로그램 코드Compiled time사용자가 작성한 모든 함수/라이브러리 함수들의 코드
데이터(data) 영역전역 변수(global)
정적 데이터(static)
Compiled timerdata, data, bss 등으로 구분됨
사용자 프로그램, 라이브러리 포함
프로세스 적재시 할당, 종료시 소멸
힙(heap) 영역실행중 동적 할당된 객체Runtimemalloc() 등으로 할당받는 공간은 힙 영역에서 할당됨
힙 영역에서 아래 번지로 내려가면서 할당
스택(stack) 영역함수 내 지역적인 객체Runtime매개변수, 지역변수, 함수 종료 후 돌아갈 주소 등이 저장됨
함수 호출 시, 스택 영역에서 위쪽으로 공간 할당
함수 return시 할당된 공간 반환함

프로세스의 메모리 구조 프로세스의 메모리 구조

이처럼 메모리 구조가 영역이 구분된 이유는 다음과 같다.

  • 데이터를 공유하여 메모리 사용량을 줄이기 위함이다.
  • 스택 구조와 전역 변수의 활용성을 위해서이다.

3.1. Code 영역이 구분된 이유

  • 프로그램 코드는 컴파일되고 나서는 바뀔 일이 전혀 없음 → Read-Only
  • 같은 프로세스가 여러 프로세스로서 실행될 때, 코드 영역을 공유(Share)함으로서 메모리 사용량 감소 가능

3.2. Data 영역이 구분된 이유

  • 전역변수/정적(static)변수 저장 영역 → Read-Write (참고: 리터럴(literal)들은 read-only)
  • 전역/정적변수 → 프로그램 실행되는 동안 항상 접근 가능해야 함 → 프로그램 실행과 관계 없이 독립적 영역이 필요하다.

3.3. Heap 영역이 구분된 이유

  • 프로그램 실행 도중 필요시마다 할당받는 공간 → 얼마나 필요할 지 예측 불가

3.4. Stack 영역이 구분된 이유

  • 프로그램은 함수의 호출로 이뤄짐(함수는 프로그램의 실행 단위)
    • 지역변수, 매개변수, 반환 값 등이 존재함
  • 스택 구조 이용하면 함수 호출 순서/반환 대상 등 관리가 편해진다
    • Callstack: 스택 프레임을 통한 함수의 실행 순서 구분

Stack 영역이 구분된 이유

3.5. Heap, Stack이 자라나는 방향이 다른 이유

  • Heap, Stack은 실행 상태에 따라 얼마나 사용될지 모름
    • 동적 공간에서 서로 공간을 유용하게 활용하기 위해서이다.

4. 프로세스 주소 → 물리 주소 변환

가상 메모리에서 다시 등장하는 개념이다.

프로세스 주소 to 물리 주소






각주

  1. 이를 1 Word라 하며, CPU 아키텍쳐 크기(32 bit, 64 bit 등)와 같다. 

이 포스팅은 작성자의 CC BY-NC 4.0 라이선스를 준수합니다.