7 메모리 관리

5 minute read

7. 메모리 관리

1. 주소 바인딩

  • 논리적 주소 혹은 가상 주소
    • 프로그램이 실행을 위해 메모리에 적재되면 그 프로세스를 위해 생성되는 독자적인 주소 공간
  • 물리적 주소
    • 물리적 메모리에 실제로 올라가는 위치, 낮은 주소 영역에는 운영체제가, 높은 주소 영역에는 사용자 프로세스들이 올라감
  • 주소 바인딩 : 프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜주는 작업
    • 프로그램이 적재되는 물리적 메모리의 주소가 결정되는 시기에 따라 3가지로 분류
      1. 컴파일 타임 바인딩 (compile time binding)
      • 프로그램을 컴파일할 때 물리적 메모리 주소가 결정되는 주소 바인딩 방식
      • 컴파일을 하는 시점에 해당 프로그램이 물리적 메모리의 몇 번지에 위치할 것인지를 결정
      • 프로그램이 절대주소로 적재된다는 뜻에서 절대코드를 생성하는 바인딩 방식이라고도 부름
      • ❌ 물리적 주소를 변경하고 싶다면 컴파일을 다시 해야 함 ⇒ 비현실적, 잘 사용 x 2. 로드 타임 바인딩 (load time binding)
      • 프로그램의 실행이 시작될 때 물리적 메모리 주소가 결정되는 주소 바인딩 방식
      • 로더(사용자 프로그램을 메모리에 적재시키는 프로그램)의 책임하에 물리적 메모리 주소가 부여되며 프로그램이 종료될 때까지 물리적 메모리상의 위치가 고정됨
      • 컴파일러가 재배치 가능 코드를 생성한 경우, 가능한 방식 3. 실행시간 바인딩 (execution time binding 또는 run time binding)
      • 프로그램이 실행을 시작한 후에도 그 프로그램이 위치한 물리적 메모리상의 주소가 변경될 수 있는 바인딩 방식
      • CPU가 주소를 참조할 때마다 해당 데이터가 물리적 메모리의 어느 위치에 존재하는지, 주소 매핑 테이블(address mapping table)을 이용해 바인딩을 점검해야 함
      • 다른 방식들과 달리 기준 레지스터와 한계 레지스터를 포함해 MMU(Memory Management Unit, 메모리 관리 유닛 : 논리적 주소를 메모리 주소로 매핑해주는 하드웨어 장치) 필요함
  • MMU (Memory Management Unit) 기법 : 가장 기본적인 방식으로 주소 변환을 수행하는 기법
    • 특정 프로세스의 주소값에 기준 레지스터의 값을 더해 물리적 주소값을 얻어냄
    • 프로그램의 주소공간이 물리적 메모리의 한 장소에 연속적으로 적재되는 것을 가정
    • 한계 레지스터
      • 현재 CPU에서 수행 중인 프로세스의 논리적 주소의 최댓값, 즉 그 프로세스의 크기, 프로세스가 자신의 주소 공간을 넘어서는 메모리 참조를 하려고 하는지 체크하는 용도로 사용 1. 프로세스의 논리적 주소값이 한계 레지스터보다 작은지 확인 2. 작다면, 논리적 주소값에 기준 레지스터 값을 더해 물리적 주소를 구한 다음 해당 물리적 메모리 위치에 접근하도록 허락 3. 크다면, 다른 프로세스의 주소 영역에 접근하려는 시도이므로 트랩을 발생시켜 해당 프로세스 강제종료

2. 메모리 관리와 관련된 용어

동적로딩

  • 여러 프로그램이 동시에 메모리에 올라가서 수행되는 다중 프로그래밍 환경에서 메모리 사용의 효율성을 높이기 위해 사용하는 기법
  • 프로세스 실행 시 프로세스의 주소 공간 전체가 메모리에 적재되는 것이 아니라, 실행에 필요한 부분이 실제로 불릴 때마다 메모리에 적재하는 방식
  • ✅ 메모리 이용의 효율성 향상

동적연결

  • 연결 : 프로그래머가 작성한 소스 코드를 컴파일하여 생성된 목적 파일과 이미 컴파일된 라이브러리 파일들을 묶어 하나의 실행파일을 생성하는 과정
  • 정적연결 : 프로그래머가 작성한 코드와 라이브러리 코드가 모두 합쳐져서 실행파일 생성 ⇒ 실행파일의 크기가 상대적으로 크고, 동일한 라이브러리를 각 프로세스가 개별적으로 메모리에 적재해야 하므로 물리적 메모리가 낭비됨
  • 동적연결 : 컴파일을 통해 생성된 목적 파일과 라이브러리 파일 사이의 연결을 프로그램의 실행 시점까지 지연시키는 방법
    • 정적연결과 달리 라이브러리가 실행 시점에 연결되기 때문에 실행 파일에 라이브러리 코드가 포함되지 않으며, 프로그램이 실행되면서 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어짐
    • 실행파일의 라이브러리 호출 부분에 해당 라이브러리 위치를 찾기 위한 스텁(stub)이라는 작은 코드를 두고 라이브러리 호출 시 스텁을 통해 해당 라이브러리가 메모리에 이미 존재하는지 확인 ⇒ 있으면 직접 참조, 없으면 디스크에서 찾아 적재한 후 수행
    • ✅ 다수의 프로그램이 공통으로 사용하는 라이브러리를 메모리에 한 번만 적재하므로 메모리 사용의 효율성 향상

중첩 (overlays)

  • 프로세스의 주소 공간을 분할해 실제 필요한 부분만을 메모리에 적재하는 기법
  • 중첩 vs 동적로딩
    • 중첩 : 초창기 컴퓨터 시스템에서 물리적 메모리의 크기 제약으로 인해 하나의 프로세스조차 메모리에 한꺼번에 올릴 수 없을 때, 프로세스의 주소 공간을 분할해서 당장 필요한 부분만 울리기 위해 사용했음 ⇒단일 프로세스만 메모리에 올려놓는 환경에서 메모리 용량보다 큰 프로세스를 실행하기 위해
    • 동적로딩 : 다중 프로그래밍 환경에서 메모리 이용률 향상을 위해 사용 ⇒ 메모리에 더 많은 프로세스를 동시에 올려놓고 실행하기 위해

스와핑 (swapping)

  • 메모리에 올라온 프로세스의 주소 공간 전체를 디스크의 스왑 영역에 일시적으로 내려놓는 것
  • 다중 프로그래밍의 정도(메모리에 존재하는 프로세스의 수)를 조절하기 위해 사용

  • 스왑 영역, 백킹스토어
    • 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역
    • 프로세스가 수행 중인 동안에만 디스크에 일시적으로 저장하는 공간(휘발성)
    • 다수의 사용자 프로세스를 담을 수 있을 만큼 충분히 큰 저장공간이어야 하고 어느 정도의 접근 속도가 보장되어야 함
    • 프로세스가 종료되어 주소공간을 디스크로 내쫓는 것이 아니라, 특정한 이유로 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것
    • 디스크 → 메모리 : 스왑 인, 메모리 → 디스크 : 스왑 아웃
  • 과정
    • 스와퍼라고 불리는 중기 스케줄러가 스왑아웃시킬 프로세스 선정
    • 선정된 프로세스에 대해 현재 메모리에 올라가 있는 주소 공간의 내용을 통째로 디스크 스왑 영역에 스왑 아웃
    • 남아있는 프로그램이 충분히 실행되고 나면, 다시 스왑 아웃되었떤 프로그램을 올림
  • 프로그램의 물리적 주소가 변하지 않는 컴파일 타임 바인딩, 로드 타임 바인딩 방식에서는 스왑아웃된 프로세스가 다시 스왑 인 될 때 원래 존재하던 메모리 위치로 다시 올라와야 함
  • 프로그램의 물리적 주소가 변할 수 있는 실행시간 바인딩 방식에서는 추후 빈 메모리 영역 아무곳에나 프로세스를 올리면 됨

3. 물리적 메모리의 할당 방식

  • 프로세스를 메모리에 올리는 방식에 따른 분류
  1. 연속할당 (contiguous allocation) : 각 프로세스를 물리적 메모리의 연속적 공간에 올리는 방식
    • 메모리를 분할하는 방식(분할을 관리하는 방식)에 따라 고정분할, 가변분할
  2. 불연속할당 (noncontiguous allocation) : 하나의 프로세스를 물리적 메모리의 여러 영역에 분산해 적재하는 방식
    • 프로세스를 분할하는 방식에 따라 페이징, 세그멘테이션, 페이지드 세그멘테이션

연속할당

  • 메모리를 분할하는 방식에 따른 분류

    1. 고정분할 방식 : 물리적 메모리를 고정된 크기의 분할로 미리 나누어두는 방식
      • 물리적 메모리를 주어진 개수만큼의 영구적인 분할로 미리 나누어두고 각 분할에 하나의 프로세스를 적재
      • 분할의 크기는 모두 동일하게 할 수도 있고 서로 다르게 할 수도 있음
      • ❌ 하나의 분할엔 하나의 프로그램만 적재가능하기 때문에 동시에 메모리에 올릴 수 있는 프로그램의 수가 고정되어 있음
      • ❌ 수행 가능한 프로그램의 최대 크기도 제한되어 있음
      • ❌ 외부조각(프로그램의 크기 > 분할의 크기)과 내부조각(프로그램의 크기 < 분할의 크기)이 발생
    2. 가변분할 방식 : 분할을 미리 나누어놓지 않고, 프로그램이 실행되고 종료되는 순서에 따라 분할을 관리하는 방식
      • 메모리에 적재되는 프로그램의 크기에 따라 분할의 크기, 개수가 동적으로 변하는 방식
      • ✅ 분할의 크기를 프로그램의 크기보다 크게 할당하지 않기 때문에 내부조각 발생 x
      • ❌ 이미 메모리에 존재하는 프로그램이 종료될 경우 중간에 빈 공간이 발생하게 되므로 외부조각은 발생할 수 있음
      • 크기가 n인 프로세스를 메모리에 올릴 때 물리적 메모리 내 가용 공간(메모리에 산발적으로 존재하는 빈공간) 중 어떤 위치에 올릴 것인가?
    • 최초적합 (first-fit) : 크기가 n이상인 가용 공간 중 가장 먼저 찾아지는 곳에 프로세스 할당
      • ✅ 가용 공간을 모두 탐색하지 않아도 되므로 시간적 측면에서 효율적
    • 최적적합 (best-fit) : 크기가 n이상이면서 가장 작은 가용 공간에 프로세스 할당
      • ✅ 공간적 측면에서 효율적
      • ❌ 가용 공간들이 크기순으로 정렬되어 있지 않은 경우, 모든 가용공간을 탐색해야 하므로 시간적 오버헤드 발생
      • ❌ 다수의 매우 작은 가용 공간들이 생성될 수 있음
    • 최악적합 (worst-fit) : 가장 크기가 큰 곳에 새로운 프로그램 할당
      • ❌ 최적적합과 마찬가지로 모든 가용 공간들을 탐색해야 하는 오버헤드 발생
      • ❌ 상대적으로 더 큰 프로그램을 담을 수 있는 가용 공간을 빨리 소진한다는 문제점
    • 컴팩션 (compaction) : 가용 공간들을 한쪽으로 모아서 하나의 큰 가용 공간을 만드는 방법
      • ✅ 외부조각 문제를 해결
      • ❌ 현재 수행 중인 프로세스의 메모리상 위치를 상당부분 이동시켜야 하므로 비용이 많이 듬
      • ❌ 수행 중인 프로세스의 물리적 위치를 옮기는 것이므로 실행시간 바인딩 방식이 지원되는 환경에서만 가능

불연속할당

  • 프로세스를 분할하는 방식에 따른 분류
    1. 페이징 : 각 프로세스의 주소 공간을 동일한 크기의 페이지로 잘라 페이지 단위로 적재시키는 방식
    2. 세그멘테이션 : 코드, 데이터, 스택 등 의미 있는 단위인 세그먼트로 나누어 세그먼트 단위로 적재시키는 방식
    3. 페이지드 세그멘테이션 : 세그먼트 하나를 다수의 페이지로 구성하는 방식

Leave a comment