CS 지식/Operating System

운영체제 8 - (Main memory management)

눈오는1월 2024. 7. 22. 17:41
728x90

해당 정리는 youtube HPC Lab. KOREATECH의 OS 강의를 듣고 정리한 내용입니다.

강의 자료는 https://hpclab.tistory.com/1?category=887083 해당 링크에 있습니다.

 

목차

  • 메모리
    • 메모리 계층구조
    • Address Binding
      • compile time binding
      • Load time binding
      • Run time binding
    • Dynamic Loading
  • Memory Allocation
    • Continuous Memory Allocation(연속할당)
      • Uni-programming
      • Multi-programming
      • Coalescing holes(공간 통합)
      • Storage compaction(메모리 압축)

메모리

메모리는 레지스터, 캐시, 메인 메모리, 보조기억장치 이렇게 4가지가 존재한다.

레지스터에 가까워질수록 속도는 빠르지만 용량이 적고, 비싸다. 보조기억장치에 가까워질수록 속도는 느리지만, 가격이 저렴하고 용량이 크다.

이때 레지스터, 캐시는 HW가 관리를 하고, 메인 메모리, 보조기억장치는 SW가 관리한다.(OS)

메모리에 관한 기본적인 개념에 대해서 알아보자.

메모리 계층구조

여기서 중요한 단어 2가지를 알아보자

Block : 보조기억장치와 주기억장치사이엥 데이터 전송 단위이다.(1 ~ 4kb)

Word : 주기억장치와 레지스터 사이의 데이터 전송 단위이다. (16 ~ 64bit)

 

컴퓨터 사양에서 64bit라고 적혀있는 것은 word의 단위로 생각을 해도 된다.

Address Binding

프로그램 논리 주소를 실제 메모리의 물리 주소로 매핑하는 작업을 의미한다.

이 Binding은 시점에 따라 분류를 할 수 있다.

위 사진은 코드가 동작하기까지의 과정을 나타낸다. 이 과정에서 3가지 시점이 있다.

Compile time binding

소스코드를 작성하고 실행을 시키면 맨 처음 컴파일러가 소스코드를 오브젝트 모듈로 변환시키는데 이 시점에서 주소를 매핑하는 것을 Compile time binding이라고 한다.

이는 컴파일러가 메모리에 대해서 완벽히 이해하고 있어야 하고, 프로그램 전체가 메모리에 올라가야 하는 한계점이 존재한다.

Load time binding

Object module을 Linker를 통해 실행 가능한 형태인 Load module을 만들고 Loader를 통해 메모리에 올라가 과정에서 주소를 매핑하는 과정을 Load time binding이라고 한다.

이때 메모리 적재 위치를 컴파일 시점에서 모르기 때문에 상대 주소를 생선 한다. 즉, 현재 위치를 u라고 잡으면 얼마나 떨어져 있는가를 기준으로 잡는 것을 의미한다.

이후 메모리 적재 시점에서 시작 주소를 반영해서 코드 상의 주소를 재설정한다.

이 시점 역시 프로그램 전체가 메모리에 올라와야 한다.

Run time binding

메모리에 올라와 프로그램이 실행되는 중에 주소를 매핑하는 것을 Run time binding 의미한다. 즉 Ready 상태에서 Running 상태로 바뀐다. 이때 Running 상태에서 주소가 매핑되는 것이다.

이 방법은 HW(MMU : Memory Management Unit)의 도움이 필요로 한다.

대부분의 OS가 사용한다.

Dynamic Loading

모든 루틴(function)을 디스크에 저장하고 실행 전에 메모리에 올리지 않는다. 이후 루틴이 호출된 시점에서 address binding을 수행하는 것을 의미한다.

호출 시점에서 메모리에 적재하기 때문에 메모리 공간을 효율적으로 사용하는 장점이 있다.

Memory Allocation

메모리 할당에 대해서 알아보자

메모리 할당은 크게 Continuous Memory Allocation(연속할당), Non-continuous Memory Allocation(비연속할당) 이렇게 있다. (이번 시간에는 연속할당만 다뤄보고 비연속할당은 다음시간에 알아보자)

Continuous Memory Allocation(연속할당)

프로세스를 하나의 연속된 메모리 공간에 할당하는 방법을 의미한다.

메모리에 올라갈 수 있는 프로세스 수에 따라 Uni-programming, Multi-programming 2가지로 분류할 수 있다.

Uni-programming

하나의 프로세스만 메모리에 올라가는 것을 말한다.(그만큼 아주 단순한 구조이다.)

이 방식에 여러 고려사항이 존재한다.

  1. 프로그램 크기가 메모리 크기보다 클 경우 어떻게 해야 할까

사용자가 프로그램의 흐름 및 자료구조를 모두 알고 있다는 가정하에 메모리에 현재 필요한 영역만 적재하는 것이다.

  1. 커널을 어떻게 보호해야 할까?

메모리에 올라갈 때 커널을 침범하게 될 경우 문제가 생긴다. 그래서 Boundray address라는 것이 있는데 이것을 통해서 커널을 침범하지 못하게 막을 수 있다.

  1. 공간이 낭비된다.

하나의 프로세스만 메모리에 올라가는데 이때 프로세스의 크기가 너무 작으면 그만큼 공간이 낭비될 수 있다. 공간이 낭비가 되면, 자원의 활용이 감소되고 퍼포먼스가 줄어들다. 이는 프로세스를 여러 개 올리는 Multi-programming으로 해결할 수 있다.

Multi-programming

메모리에 여러 개의 프로세스를 올리는 것을 의미한다.

여러 프로레스를 올리는 방법으로 FPM(Fixed partition multi-programming), VPM(Variable partition multi-programming으로 분류할 수 있다.

 

FPM(Fixed Partition Multiprogramming)

제목 의미로 메모리 공간을 고정된 크기로 (미리) 분할하는 방식이다.

분할된 공간(파티션)은 하나의 프로세스가 들어갈 수 있다.

또한 각각의 영역과 커널을 보호하기 위해 Boundray address를 활용해서 영역을 보호한다.

잠시 fragmentation에 대해서 알아보자.

 

Multi-programming에서 **Fragmentation(단편화)**라는 중요한 개념이 존재한다. Fragmentation은 Internal fragmentation, External fragmentation 2가지가 존재한다.

Internal fragmentation

말 그대로 내부 단편화이고, 파티션의 크기가 프로세스의 크기보다 큰 것을 의미한다. 프로세스의 크기가 더 작기 때문에 파티션의 남는 메모리가 존재하기 때문에 메모리가 낭비되는 것을 의미한다.

External fragmentation

외부 단편화이고, 위 그림처럼 남는 메모리 크기가 들어오려고 하는 프로세스 크기보다 크지만, 메모리가 연속적이지 않아 낭비되는 것을 의미한다.

 

FPM에서는 Internal fragmentation과 External gragmentation 둘 다 발생한다.

 

VPM(Variable Partition Multiprogramming)

말 그대로 파티션의 크기가 정해지지 않는 것을 의미한다.

프로세스를 처리할 때 메모리 공간을 동적으로 분할한다. 그래서 No internal fragmentation이 생기지 않는다.

VPM에서는 메모리에 프로세스를 어떻게 배치하는지가 중요하다.

 

이게 무슨 말인지 예를 한번 보면,

현재 메모리에 ABCDE를 올린다고 쳐보자 각각의 크기에 맞게끔 메모리에 순서대로 올라갈 것이다. 이후 B프로세스가 종료되고 D프로세스가 종료된다고 쳐보자.

위 그림처럼 될 것이다. 이때 프로세스 P(5MB) 짜리를 추가로 메모리에 올린다고 했을 때, 어느 공간에 올릴지 결정해야 한다. 이것을 배치 전략(Placement strategies)라고 한다.

이제부터 배치전략의 종류와 각각의 특징에 대해서 알아보자.

 

배치 전략(Placement strategies)

First-fit(최초 적합)

메모리 처음주소부터 시작해서 프로세스가 사용할 수 있는 크기를 가진 파티션을 선택하는 방식이다.

간단하고 O(N) 시간 내에 가능한 만큼 overhead가 적다.

단점으로는 공간 활용률일 떨어질 수 있는데 14kb 공간에 13kb가 들어가게 되면 1kb가 남는데, 남는 공간이 너무 작아서 효율성이 떨어질 수 있다. 또한, 만약 50kb 38kb를 넣게 되면 나중에 큰 메모리가 필요한 프로세스가 있을 경우 넣을 공간이 없다. 즉, 큰 공간 효율을 제대로 사용하지 못하게 되는 것이다.

 

Best-fit(최적 적합)

메모리의 남는 공간을 다 탐색한 후 공간이 제일 적게 남는 것을 선택하는 방법이다.

위 방식은 전체를 다 탐색을 해야 하기 때문에 탐색시간이 오래 걸리고 이는 overhead가 커진다.

공간이 큰 파티션을 유지할 수 있기 때문에 큰 공간을 효율적으로 사용할 수 있지만, 단점으로는 남는 공간이 작기 때문에 활용할 가능성이 낮다.

 

Worst-fit(최악 적합)

Best-fit과 완전히 반대로 공간이 제일 많이 남는 곳을 선택하는 방법이다.

마찬가지로 전체를 다 탐색하기 때문에 탐색시간이 오래 걸기고, overhead다 크다.

큰 크기의 파티션을 효율성이 있게 활용할 수는 없지만 작은 크기의 파티션의 발생을 줄여준다.

 

Next-fit(순차 최초 적합)

First-fit과 유사한 방식이지만 다른 점은 맨 처음부터 탐색하는 것이 아니라 State table에서 마지막으로 탐색한 위치부터 탐색하는 방식이다.

이는 메모리 영역의 사용 빈도를 균등화하게 만들어줄 수 있다. 또한 전체를 탐색하는 것이 아니라 overhead가 작다.

VPM은 External fragmentation이 발생한다.

위 그림처럼 메모리가 남았을 때 프로세스 P가 메모리 50MB가 필요하게 되면 External fragmentation이 발생하는 것이다.

이를 위한 해결방법이 2가지가 있다.

Coalescing holes(공간 통합)

Colaescing holes란 말 그대로 공간을 통합하는 즉, 인접한 사용하지 않는 메모리 영역들을 하나의 파티션으로 합치는 것을 의미한다.

그래서 큰 프로세스가 메모리를 필요하게 되면, 인접한 영역을 통합해서 제공하고 만약 그래도 부족할 경우 인접한 프로세스가 종료되면 해당 부분을 통합한 후 메모리를 제공하게 된다.

Storage Compaction(메모리 압축)

해당 방법은 빈 공간을 하나로 통합하는 것이다. 즉, 중간에 빈 파티션이 있을 경우 사용 중인 프로세스를 중지시킨 후 프로세스끼리 인접할 수 있도록 재배치하는 것이다.

이러한 방법은 공간 통합 방식보다 overhead가 크게 발생한다. 그렇기에 자주 발생하지 않게끔 한다.

 

번외

메모리할당 관련된 공부를 왜 해야 하는지에 대해서 생각해 보자

만약 동적할당(malloc, new)등이 많이 쓰이는 코드가 있다고 생각해 보자. 동적할당은 비싼 연산이다. 그만큼 속도도 느리다. Systemcall 함수를 통해 매번 OS로부터 메모리를 어더와 야 하기 때문이다. 이를 효율적으로 짜려면 Memory pool을 써서 메모리를 한 번에 받은 후에 메모리를 할당해 주면 매번 메모리를 할당받는 과정일 줄어들어 빠른 속도 향상을 이뤄낼 수 있다. 또한 한 번에 받은 메모리를 관리하는데 FPM, VPM 방식을 우리는 사용할 것이다. 때문에 해당 부분에 대해서 잘 알아둬야 한다.

 

728x90