[CS] 메모리(Memory)에 대하여 - (2)

조재훈·2024년 11월 11일
0

메모리

저번 포스트에서 메모리에 대해 간단한 지식만 다뤘다면 오늘은 메모리와 관련해 조금 더 심화된 내용을 다뤄보려고 한다

가상 메모리

가상 메모리는 저번에 간단하게 다뤘는데 오늘 좀 더 깊이 다뤄보자

가상 메모리는 프로그램이 실제 물리 메모리(RAM)보다 더 많은 메모리를 사용할 수 있게 해주는 기법이다

이를 통해 프로그램이 필요한 메모리를 동적으로 할당받고, 제한된 RAM보다 더 많은 메모리를 할당받아 실행할 수 있다

가상 메모리는 프로그램을 실행시키는데 최소한의 메모리가 필요한가에 대한 접근 방식으로, 실행에 필요한 일부분만 메모리에 로드하고 나머지는 디스크에 두고 필요할 때마다 교체하면서 쓰는 방식으로 구현된다

가상주소와 물리주소

  • 가상 주소 : 프로그램이 참조하는 주소로, 프로그램은 실제 메모리의 위치를 알지 못한다. 각 프로그램마다 고유한 가상 주소 공간이 주어진다
  • 물리 주소 : 실제 메모리(RAM)에서 데이터를 저장하는 위치
  • 메모리 관리 장치(MMU) : CPU가 가상 주소로 접근할 때 이를 물리 주소로 변환하는 역할. 하드웨어임

페이지와 페이징

가상 메모리는 페이지라는 고정된 크기의 블록으로 나누어 관리된다. 물리적 메모리도 같은 크기의 페이지 프레임으로 나뉜다

페이징은 페이지 단위로 가상 메모리와 물리 메모리를 연결하는 기법으로, 필요한 페이지만 물리 메모리에 로드된다

페이지가 필요한 시점에만 물리 메모리로 옮겨지는 지연 로딩 기법을 사용하여, 전체 메모리 공간을 효율적으로 사용한다

CPU에서 논리 주소를 MMU에 보내면 변환을 거쳐 물리 주소에 저장된 데이터를 가져오는데(매핑) 이 변환 과정은 Page Table을 통해 이루어진다

가상 주소가 v = (p, d)라면
p : 가상 메모리 페이지(페이지 번호)
d : p 안에서 참조하는 위치(오프셋)

페이지 테이블에 가상 주소가 포함된 페이지 번호가 있는지 확인하고 페이지 번호가 있으면 이 페이지가 매핑된 물리 주소를 알아내고 오프셋을 더하면 실제 물리 주소가 된다

과정

  1. 프로세스 생성 시 페이지 테이블 정보 생성
  2. PCB 등에서 해당 페이지 테이블에 접근 가능하고, 관련 정보는 물리 메모리에 적재
  3. 프로세스 실행 시 해당 페이지 테이블 base 주소가 CR3이라는 레지스터에 저장
  4. CPU가 가상 주소 접근 시, MMU가 페이지 테이블 base 주소에 접근해 물리 주소를 가져옴

TLB(Translation Look-aside Buffer)

위에서 물리 주소를 얻어올려면 페이지 테이블에 접근하고 물리 메모리를 확인하는 2번의 과정이 필요하다

이 과정이 CPU 입장에서는 상당한 시간이라 이를 줄이고자 등장한게 TLB이다

TLB는 일종의 페이지 정보 캐시라고 하며 최근에 CPU가 요청한 가상 주소에 대한 물리 주소 정보를 저장하고 있어 요청한 주소가 이미 TLB에 있는 경우 메모리에 접근할 필요가 없어 훨씬 빠르다

요구 페이징(Demand Paging)

프로세스의 모든 데이터를 메모리로 적재하지 않고, 실행 중 필요한 시점에만 메모리에 로드하는 기법을 요구 페이징이라고 한다

가상 메모리 시스템에서 많이 사용되며 한 번도 접근되지 않은 페이지는 물리 메모리에 적재되지 않는다

페이지 폴트(Page Fault)

프로그램이 요청한 페이지가 물리 메모리에 없을 때 발생한다. 페이지 폴트가 일어나면 운영체제가 해당 페이지를 디스크에서 RAM으로 불러온다

페이지 폴트가 빈번하게 발생하면 디스크 접근이 많아지므로 성능이 저하되는데 이걸 막으려면 자주 쓰일 페이지를 미리 예측해 로드해놓아야 한다(가능?)

페이지 교체

페이지 폴트가 일어나면 요청된 페이지를 디스크에서 메모리로 가져오는데 이때 메모리 공간이 부족할 수 있다

그러면 메모리에 있는 기존 페이지 중 하나를 디스크로 내리고 새로운 페이지를 메모리로 올리는데 이것을 페이지 교체라고 한다

이때 어떤 페이지를 교체할 지를 결정하는 알고리즘이 필요하며 좋은 알고리즘은 최대한 페이지 폴트가 적게 일어나는 알고리즘을 선택해야 한다

FIFO

메모리에 로드된 페이지 중 가장 먼저 들어온(오래된) 페이지를 교체한다

LRU(Least Recently Used)

더 이상 참조되지 않을 것 같은 페이지를 교체한다. 가장 오래전에 참조된 페이지를 교체

LFU(Least Frequently Used)

참조 횟수가 가장 적은 페이지를 교체한다. 카운트 시점에 따라 두 가지 방식이 있음

OPT

최적 페이지 교체 알고리즘인데 앞으로 오랫동안 사용하지 않을 페이지를 교체하는 것임

사실 구현이 불가해서 연구 목적

장점

  • 메모리 효율성 증대
    • 모든 프로그램이 동시에 모든 메모리를 필요로 하지 않기에 실제로 사용 중인 메모리만 물리 메모리에 로드해 메모리를 효율적으로 사용 가능
  • 다중 프로세스 실행 지원
    • 각 프로세스가 독립적인 가상 주소 공간을 가지므로 프로세스 간 메모리 간섭 없이 안전하게 여러 프로그램을 실행 가능
  • 메모리 공간 확장
    • 제한된 RAM보다 큰 가상 주소 공간을 제공해 물리적 메모리 한계를 넘어 더 많은 메모리 사용 가능

단점

  • 속도 저하
    • 페이지 폴트가 자주 발생하면 프로그램의 성능이 급격히 저하됨. 이를 스와핑이라고 하며, 디스크와 RAM 간 잦은 데이터 교환이 문제를 일으킨다
  • 메모리 관리 복잡성 증가
    • MMU와 같은 하드웨어 지원이 필요하며, 운영체제도 페이지 교체 알고리즘과 같은 복잡한 관리 기법이 필요함
  • 페이지 단편화 문제
    • 페이지 단위로 메모리를 관리하므로, 일부 페이지의 공간이 사용되지 않는 내부 단편화 문제가 발생

참고

주형님 블로그
개발지망생님 블로그
제라스님 블로그

메모리 단편화 / 파편화(Memory Fragmentation)

개발자는 개발하면서 메모리의 할당과 해제를 반복한다. C++ 개발자라면 메모리를 직접 할당하고 해제하며 C# 개발자는 메모리를 할당하고 안 쓰이는 메모리는 GC가 알아서 메모리를 해제한다

계속되는 할당과 해제 과정에서 메모리는 점점 할당된 공간과 비어있는 공간으로 나뉘게 되며 할당 시 비어있는 공간을 계속 찾아 할당할 수 있는 크기만큼 메모리가 있다면 할당을 하게 된다

그러다가 메모리를 할당해야 할 상황에 메모리를 봤더니 메모리 전체적으로 보면 할당할 수 있는 충분한 공간이 있는데 연속적이고 할당 가능한 메모리 공간은 없을 수 있다

메모리가 다음과 같이 있을 때 [][.][][.][], 1번째와 3번째 공간에 이미 메모리가 할당되어 있다. 근데 메모리 두 칸을 할당해야 할 때 메모리에 남은 공간은 3칸인데 연속적인 2칸이 없다

이러한 현상을 메모리 단편화라고 하며 이는 프로그램의 성능을 저하시키고 메모리를 확보하기 어렵게 만든다

메모리 단편화는 두 가지로 구분이 가능하다

외부 단편화

외부 단편화가 일반적인 단편화의 개념과 비슷하다

잦은 메모리 할당과 해제로 크기가 다양한 메모리 조각들이 메모리 전체적으로 흩어져 있다. 그래서 연속적인 큰 메모리를 할당해야 할 때 할당이 불가능하다(위의 예시와 비슷)

내부 단편화

내부 단편화는 할당된 메모리 블록 중 실제로 사용하지 않는 공간이 생겨 메모리 낭비가 발생하는 경우다

메모리를 할당할 때 넉넉잡아 프로세스가 요구하는 메모리보다 큰 메모리를 할당했을 때 발생

메모리를 고정된 크기로 할당할 때 자주 발생한다

단편화 해결 방법

메모리 압축

할당중인 메모리 블록을 한 곳으로 몰아 연속된 빈 공간을 확보하는 방법

  • 장점 : 외부 단편화를 해결하고 연속된 메모리 공간을 만들 수 있음
  • 단점 : 실행 중인 프로그램을 중단하고 메모리를 재배치해야 해서 시간이 많이 걸림

페이징 기법

가상 메모리에서 다루던 페이징 기법이다

메모리를 고정된 크기로 나누고 각 페이지를 독립적으로 관리한다. 프로세스가 필요로 하는 페이지만 할당하고 페이지를 가상 메모리 주소에 매핑하여 사용한다

페이징 기법을 사용하면 연속적이지 않은 공간도 활용할 수 있어 외부 단편화를 해결할 수 있지만 페이지 크기에 따라 내부 단편화가 발생할 수 있음

세그멘테이션 기법

메모리를 같은 크기의 페이지로 관리했던 페이징 기법과 달리 세그멘테이션 기법에서는 가상 메모리를 서로 크기가 다른 논리적 단위의 세그먼트로 분할한 후 메모리를 할당하여 실제 메모리 주소로 변환한다

각 세그멘테이션은 연속적인 공간에 저장되는데 메모리에 로드될 때 빈 공간에 할당된다. 매핑을 위해 세그멘트 테이블이 필요함

프로세스가 필요한 메모리만큼 할당을 하기에 내부 단편화를 해결할 수 있지만 외부 단편화를 해결하지는 못한다

메모리 풀

개발자가 필요한 메모리 공간의 개수, 크기를 지정하여 미리 할당받아 놓고 필요할 때마다 사용하고 반납하는 기법이다

메모리 풀 없이 할당과 해제를 반복하면 단편화가 일어날 수 있지만 미리 공간을 할당하기에 외부 단편화가 일어나지 않는다

그리고 필요한 크기만큼 할당을 해놓기 때문에 내부 단편화 또한 일어나지 않는다

하지만 메모리 단편화로 인한 메모리 낭비보다 메모리 풀을 만들어 놓고 쓰지를 않는다면 그게 더 낭비다

그러므로 메모리 할당과 해제가 잦을 때 사용해야 한다

profile
나태지옥

0개의 댓글