COMPUTER SCIENCE/OS

[쉽게 배우는 운영체제 2판] 7. 물리 메모리 관리

Tiny Commit 2025. 5. 21. 03:17

 

 

 

 

1. 메모리 관리의 개요

프로그램이 실행되어 프로세스가 된다. = 저장장치에 있는 프로그램이 메모리로 올라온다.

 

1. 메모리 이해하기

  • 메모리는 1B로 나뉘고, 그 나뉜 영역은 주소이다. CPU는 메모리에 있는 데이터를 가져오거나 작업 결과를 메모리에 저장하기 위해 주소를 사용한다. 
  • 운영체제도 메모리에 올라와야 실행할 수 있다. 이 과정을 부팅이라고 하며, 부팅이 끝나면 여러 응용프록램이 메모리에서 작업을 시작할 수 있다. 
  • CPU입장에서 메모리와의 속도차이를 상쇄하기 위해 캐시를 쓴다. (일정 부분을 미리 가져와 작업한다. )

 

 

 

2. 메모리 관리의 이중성

  • 메모리 관리 시스템
    • 일괄 처리 시스템: 한 번에 한 가지 작업
    • 시분할 시스템: 모든 응용 프로그램이 메모리에 올라와 복잡하다. 도중에 공간이 부족하면 새로운 공간을 만들어야 한다. ( 작은 공간들을 합친다. )
      • 메모리 관리의 이중성: 프로세스는 메모리를 독차지하고, 메모리관리자는 효율적으로 관리하려고 한다. 

 

3. 소스코드의 번역과 실행

메모리관리를 이해하기 위해 프로그램을 만드는 소스코드의 번역과 실행 과정

 

소스코드의 번역 방식

  • 프로그래밍 언어 -> 컴파일러 -> 실행가능한 코드 (기계어)
  • 컴파일러: 소스코드를 컴퓨터가 실행할 수 있는 기계어로 변역한 수 한꺼번에 실행한다. ( C언어, 자바)
  • 인터프리터: 소스코드를 한 행씩 번역하여 실행한다. (자바스크립트, 파이썬)

 

컴파일러 방식 : 변수 선언 -> 코드

  • 오류 발견: 심벌테이블(변수의 이름과 종류 모음): 선언하지 않은 변수, 다른 종류의 데이터를 저장하지 않았는지 확인
  • 소스 코드 최적화: 소스코드에 군더더기와 사용하지 않는 변수를 삭제하면 더욱 간결하고 빨라진다. 
  • 변수선언 필수: 오류를 찾고 코드를 최적화 하기 위해

컴파일러의 컴파일 과정

  • 목적코드: 오류점검하고 최적화로 필요없는 변수와 코드를 삭제한다. (obj) -> 최종 실행 파일
  • 라이브러리: 자주 사용하는 함수, 만들기 어려운 함수를 파일 형태로 모아 놓은것.
    • 동적라이브러리: 실행할 때 삽입되는 함수를 가진 라이브러리, 함수가 변경되어도 새로 컴파일할 필요없이 새로운 라이브러리만 사용하여 실행하면 된다. 
    • DLL: 윈도우, 특정 폴더에 삽입하여 새로운 기능을 사용할 수 있다. 

 

4. 메모리 관리 작업

  • 메모리 가져오기: 실행할 프로세스와 데이터를 메모리로 가져오는 작업
  • 메모리 배치: 가져온 프로세스와 데이터를 메모리 어디에 둘 것인지를 결정, 메모리를 어떤 크기로 자르느냐
    • 페이징(같은 크기) VS 세그먼테이션(다른 크기)
  • 메모리 재배치: 메모리가 다 차면, 메모리에 있는 프로세스를 하드디스크로 옮기고 새로운 프로세스를 메모리에 가져온다. 
    • 교체 알고리즘: 앞으로 사용하지 않을 프로세스를 찾아서 내보내는 알고리즘

 

 

 

 

 

2. 메모리 주소

메모리에 사용되는 주소는 물리 주소논리 주소가 있다. 

 

 

1. 32but CPU와 64 bit CPU의 차이

  • bit: CPU가 한 번에 다룰 수 있는 데이터의 최대 크기
  • 레지스터 크기 = 산술논리 연산장치 = 버스의 크기(대역폭) = 데이터의 크기
  • 메모리 주소 공간 = 메모리 주소 레지스터의 크기가 정해져 있으므로, 매모리 주소 범위가 한정된다.
  • 32bit CPU컴퓨터는 메모리를 최대 4GB까지 사용할 수 있다. 

 

 

 

 

2. 논리 주소와 물리 주소 

메모리 영역의 구분

  • 단순 메모리 구조 = 일괄 처리 시스템
    • 운영체제 영역과 사용자 영역을 분리하여 관리
    • 사용자 프로세스가 운영체제의 크기에 따라 매번 적재되는 주소가 달라진다. (번거롭다)
      • 최상위에서 운영체제쪽으로 내려오면서 메모리 사용 -> 주소변경시 번거로움
      • 하드웨어 도움: 경계레지스터를 벗어나면 프로세스 강제 종료

논리 주소와 물리 주소의 변환

코드가 실행되면 프로세스가 메모리에 올라온다. -> 메모리는 빈 공간에 배치된다. 

ex) 물리 메모리의 360번지부터 프로세스 사용한다. 논리 주소(40번지)에 물리 메모리 주소(400번지)가 저장된다. 

  • 물리 주소: 메모리의 입장에서 바라본 주소, 매번 바뀐다. 
  • 논리 주소: 프로세스 입장에서 바라 봄, 0번지 부터 시작. 

 

 

  • 메모리 관리 유닛: 논리 주소로 이루어진 프로세스를 실행하면 물리 주소로 변환하는 작업을 담당. 
  • 재배치 레지스터: 주소 변환의 기본이 되는 주소 값을 가진 레지스토로, 메모리에거 사용자 영역의 시작 주소 값이 저장된다. 

사용자 프로세스 입장에서는 메모리 관리자가 재배치 레지스터를 사용하여 논리 주소를 물리 주소로 변환하기 때문에 메모리가 항상 0번지부터 시작하는 연속된 작업 공간으로 보인다. 만약 운영체제 영역이 바뀌어 사용자 영역이 500번지부터 시작된다면 재배치 레지스터에 500을 넣으면 된다

 

 

 

 

 

 

 

 

 

 

3. 단일 프로그래밍 환경의 메모리 할당

1. 메모리 오버레이

과거에는 메모리가 값비싼 저장장치였기에 개인용 컴퓨터에 큰 메모리를 사용할 수 없었다.

지금은 메모리 가격이 부담스럽지 않고 용량도 넉넉하여 문제없지만 과거에는 작은 메모리로 큰 프로그램을 어떻게 작동할 것인가가 문제였다.

  • 메모리 오버레이: 적당한 크기로 잘라 서 가져오는 기법
    • 프로그램을 몇 개의 모듈로 나누고 필요할 때마다 모듈을 메모리에 가져와 사용한다.
    • 전체를 메모리에 올려놓고 실행하는 것보다 속도가 느리지만 메모리가 프로그램보다 작을 때도 실행할 수 있어 유용하다.
    • 어떤 모듈이 필요한지를 결정하는 것이 프로그램 카운터가 결정한다.
    • 일부만 메모리에 올라와도 실행할 수 있다.
    • 큰 프로그램을 실행할 수 있다.

메모리 오버레이에서는 메모리보다 큰 프로그램을 실행할 때 프로그램을 메모리보다 작은 크기의 모듈로 나누어서 사용한다.

 

 

2. 스왑

메모리 오버레이를 이용하면 메모리보다 큰 프로그램을 실행할 수 있다. 근데 안 쓴느 건 별도의 공간에 임시로 저장하면 된다.

  • 스왑 영역: 메모리가 모자라서 쫓겨난 프로세스를 저장장치의 특별한 공 간에 모아두는 영역
    • 스왑인: 스왑 영역에서 메모리로 데이 터를 가져오는 작업
    • 스왑아웃: 메모리에서 스왑 영역으로 데이터를 내보내는 작업
  • 저장장치는 장소만 빌려주고 메모리 관리자가 관리한다.
  • 스왑 영역의 크기가 메모리의 크기 로 인식된다.

 

 

 

 

 

 

 

 

 

4. 다중 프로그래밍 환경의 메모리 할당

한 번에 여러 프로세스가 실행되는 구조의 메모리 문제: 프 로세스들의 크기가 달라 메모리를 어떻게 나누어 사용할 것인지가 가장 큰 문제다

 

1. 메모리 분할 방식

  • 가변 분할 방식: 프로세스의 크기에 따라 메모리를 나눈다.
  • 고정 분할 방식: 프로세스의 크기와 상관없이 메모리를 같은 크기로 나눈다.

메모리 분할 방식의 구현과 장단점

  • 가변 분할 방식 (연속 메모리 할당)
    • 프로세스의 크기에 맞게 메모리가 분할되므로 프로세스가 차지하는 메모리 영역의 크기가 40KB에서 17KB까지 다 다르다. 물리 메모리에서 하나의 프로세스에 해당하는 주소 공간이 연속적으로 이어진다.
    • 프로세스를 한 덩어리로 처리하여 하나의 프로세스를 연속된 공간에 배치할 수 있다.
    • 메모리 관리가 복잡하다는 단점
    • 메모리 크기가 다르므로, 떨어져 있는 빈 공간들을 합쳐야 한다. (메모리 통합)
  • 고정 분할 방식 ( 비연속 메모리 할당 ) - 현대 운영체제
    • 프로세스의 크기에 상관없이 20KB의 같은 크기로 나뉜다. ( 메모리 관리가 편하다 )
    • 따라서 큰 프로세스가 메모리에 올라오면 여러 조각으로 나뉘어 배치된다.
    • 단점은 하나의 프로세스가 여러 곳으로 나뉠 수 있다는 점 -> 메모리 오버레이 + 스왑영역으로 극복

 

 

 

 

 

 

2. 가변 분할 방식의 메모리 관리

가변 분할 방식의 특징 - 세그먼테이션

  • 외부 단편화: 빈 공간의 트기가 일정하지 않다 -> 메모리 배치 방식 / 조각 모음으로 극복

 

 

 

메모리 배치 방식 - 선처리

  • 작은 조각이 발 생하지 않도록 프로세스를 배치하는 것
  • 최초 배치: 적재 가능한 공간을 순서대로 찾다가 첫 번째로 발견한 공간에 프로세스를 배치하는 방법
    • 빈 공간을 찾아다닐 필요가 없다
  • 최적 배치: 빈 공간을 모두 확인한 후 크기가 가장 비슷한 곳에 프로세스를 배치
    • 빈 공간을 모두 확인하는 부가적인 작업이 들어가지만 딱 맞는 공간을 찾을 경우 단편화가 일어나지 않는다.
    • 아주 작은 조각을 만들어낸다는 단점 -> 작은 공간은 버려질 가능성이 크다.
  • 최악 배치: 10MB 크기의 프로세스는 18MB, 12MB, 26MB의 빈 공간 중 26MB에 배치된다.
    • 프로세스를 배치하고 남 은 공간이 크기 때문에 이 공간이 쓸모가 있다.
  • 버디 시스템

 

 

 

 

조각 모음 - 후처리

  • 메모리 통합
  • 조각이 발생했을 때 작은 조각들을 모아서 하나의 큰 덩어리로 만드는 작업
  • 조각 모음을 하려면 프로세스를 멈추고, 이동하고, 주소를 바꾸고, 다시 시작하는 작업을 해 야 하므로 많은 시간이 걸린다.

 

 

 

 

3. 고정 분할 방식의 메모리 관리

  • 페이징
  • 일정하게 나뉜 메모리의 크기보다 작은 프로세스가 배치될 경우 낭비되는 공간이 생긴다 -> 내부 단편화
  • 내부 단편 화를 해결하기 위해 조각 모음을 할 수 없고 남는 공간을 다른 프로세스에 배정할 수도 없다. -> 고정 분할 방식에서는 내부 단편화를 줄이기 위해 메모리를 어떤 크기로 나눌지 신중 하게 결정해야한다.

 

 

 

 

 

 

 

 

 

4. 버디 시스템

버디 시스템의 작동 방식

  • 가변 분할 방식 - 외부 단편화 완화 방법
  • 프로세스
    • 프로세스의 크기에 맞게 메모리를 1/2로 자르고 프로세스를 메모리에 배치한다
    • 나뉜 메모리의 각 구역에는 프로세스가 1개만 들어간다.
    • 프로세스가 종료되면 주변의 빈 조각과 합쳐서 하나의 큰 덩어리를 만든다
  • 버디 시스템에서는 메모리를 분할할 땐 1/2로 나누고. 프로세 스가 종료될 때마다 주변을 살펴서 빈 구역을 하나로 합친다

버디 시스템의 특징

  • 가변 분할 + 고정 분할
    • 가변: 프로세스 크기대로 나뉘지만, 비슷한 크기의 덩어리가 서로 모여 있어서 통합하기 쉽다. 조각 모음을 하지 않아도 간단 히 큰 덩어리를 만들 수 있다.
    • 고정: 하나의 구역에 다른 프로세스가 들어갈 수 업속, 내부 단편화 발생.
  •  버디 시스템보다 고정 분할 방식을 많이 사용한다.

 

 

 

 

 

 

 

 

5. 분할 컴파일과 메모리 관리

메모리가 어떻게 배정되는지

 

1. 분할 컴파일

  • C나 자바 언어로 작성한 소스코드는 컴파일 과정을 거쳐 목적 코드가 된다.
  • 다중 소스코드: 여러 개의 소스코드 파일을 사용하여 하나의 실행 파일을 만드는 것
  • 분할 컴파일: 여러 개의 소스코드(목적파일)를 각각 컴파일하여 하나의 실행 파일로 만드는 것

 

2. 변수와 메모리 할당

  • 컴파일 과정에서 가장 중요한 것은 메모리를 확보하고 정리하는 부분이다. 
  • char str=’a’;:기계어에서 메모리 주소0번지에 a를 넣으라는 명령으로 번역되어 컴파일러는 0번지에 a를 넣고 이곳을 문자형이 들어가는 공간으로 기억한다.
  • 컴파일러는 변수를 사용할 때마다 사용 범위를 넘는지 점검한다.
  • 컴파일러는 프로그래머가 만든 변수를 적당한 크기의 메모리 주소로 변환하 여 기계어로 바꾼다.

 

 

 

 

 

 


출처 : 조성호 , 『IT CookBook, 쉽게 배우는 운영체제(2판)』한빛아카데미(2023).