메모리 계층 구조
메모리 계층 구조는 여러 종류의 기억장치를 속도, 용량, 성능에 따라 계층 적으로 나눈 것을 의미합니다.
- 레지스터와 캐시 : 레지스터는 CPU안에 캐시는 CPU와 메모리 사이에 존재함으로 CPU에 접근하기 빨라 성능이 좋다
- 주기억 장치(메모리) : CPU 외부에 존재하기에 레지스터와 캐시보다는 성능이 좋지 않다.
- 보조기억장치(하드디스크) : CPU가 접근할 수 없다. 접근하기 위해서는 하드디스크의 데이터를 메모리로 이동시켜야 한다. 때문에 많이 느리다.
- 상위 계층으로 갈수록 속도는 빠르고, 용량은 적으며 성능은 좋다.
- 상위 계층의 단점을 보완하기위해 메모리 계층 구조를 이용한다.
보조기억장치
- HDD
- 물리적인 디스크를 사용해서 데이터를 저장(디스크 회전 이용)
- 디스크에 저장되어있기 때문에 충격에 약하다
- 최근의 SSD가 나오면서 많이 사용하지 않는 분위기
- SSD
- 반도체 기반으로 정보를 저장
- 물리적으로 저장하는 것이 아닌 전기적으로 데이터를 저장
- HDD에 비해 속도가 빠르고 전력 소모가 적다
- HDD보다 가격이 비싸다
RAM, ROM
RAM
- Random Access Memory
- 1과 0의 신호로 정보를 저장(쓰기)하고 읽는 것이(읽기) 가능
- 프로그램 실행 시 필요한 정보를 저장하고 빠르게 접근 가능
- 휘발성 메모리(전원이 꺼지면 증발)
- CPU의 작업과 데이터 보관에 사용
- 반도체 회로
RAM은 크게 DRAM과 SRAM으로 나눌 수 있습니다.
- DRAM : Diynamic RAM (동적)
- Capacitor로 작동 -> 시간이 지나면 스스로 방전한다
- 때문에 방전하기 전에 Refresh 신호를 주어야한다.
- 신경써야할 것이 많기에 속도가 느리다.
- 용량이 크다 -> 가격이 싸다
- 저장용으로 사용 -> 주 메모리로 사용
- SRAM : Static RAM (정적)
- Flip-Flop으로 작동 - 전류신호가 오기 전에는 상태가 변화지 않는다
- 특정 데이터를 기억하고만 있으면 되기때문에 속도가 빠르다.
- 용량이 작다 -> 가격이 비싸다
- 캐시메모리로 사용
ROM
- Read Only Memory
- 이름 그대로 읽기만 가능
- 비휘발성 메모리 (전원이 꺼져도 증발하지 않음)
- 반영구적으로 사용가능
- 주로 시스템 프로그램을 저장(사라지면 안되는)
RAM과 ROM의 차이를 공책과 책으로 생각하면 이해하기 쉽다
주기억 장치 구조
주기억장치는 프로세스별로 나누어져있고 프로세스 자신만의 메모리 공간을 갖게됩니다.
프로세스의 메모리 공간은 Code, Data, Stack, Heap 구조로 되어있습니다.
- CODE
- 실행할 프로그램의 코드가 저장(텍스트)
- CPU가 코드의 명령어를 처리
- DATA
- 프로그램이 시작하면 할당되는 영역 -> 종료되면 소멸
- 전역변수(Global)
- 정적변수(static)
- 구조체, 클래스 정보
- BSS(Blocked Stated Symbol) 영역 : 변수들 중에 초기화 되지 않은 변수들은 이곳에 저장한다.
- HEAP
- 동적으로 할당된 객체(new 연산을 통해 생성된 객체)
- 프로그램 실행중에 생성되는 객체(인스턴스)
- 낮은 주소에서 높은 주소로 할당
- STACK
- 함수의 호출과 연관
- 임시 메모리 공간(함수의 호출과 함께 생성, 함수의 완료와 함께 소멸)
- 스택 프레임(stack frame) : 함수의 호출 정보
- 지역변수
- 매개변수
- 메서드
- return 값
- 사이즈가 고정되어 있어서 런타임시 변경 불가
Stack과 Heap 영역의 구조
- 힙과 스택은 사실 같은 공간을 공유하지만 시작지점이 다르다.
- Heap은 낮은 주소 -> 높은 주소로 할당
- stack 은 높은 주소 -> 낮은 주소로 할당
- 이렇게 서로 할당되다가 서로 겹치는 상황을 Stack/Heap Overflow라 한다.
캐시 메모리
캐시 메모리란, CPU의 처리속도와 주기억장치의 접근하는 속도 차이를 줄여주기 위해 CPU와 메모리 사이에서 사용하는 고속 Buffer Memory 이다.
특징
- 일반적으로 CPU마다 2~3개 정도 사용된다.
- 주 기억 장치에서 자주 사용되는 데이터가 있을때, 이 데이터를 캐시 메모리에 저장하여 다음에 사용할때의 속도를 향상시키는 방법입니다.
- 메모리 계층 구조에서 가장 빠른 메모리이고 처리 속도가 CPU와 비슷하다.
- 캐시 메모리를 사용하면 주 기억장치에 접근하는 횟수가 줄어들기 때문에 컴퓨터의 처리속도가 향상된다.
작동 원리
캐시가 효율적으로 동작하기 위해서는 캐시에 저장한 데이터가 지역성을 가져야 한다.
지역성 : 데이터의 접근이 시간적으로 공간적으로 가깝게 일어나야 하는 것을 의미
- 시간 지역성 : 특정 데이터가 한번 사용되었을 경우, 가까운 미래에 다시 한번 접근될 가능성이 높다.
- 공간 지역성 : 특정 데이터가 한번 사용되었을 경우, 그 주변의 인접한 데이터가 접근될 가능성이 높다.
캐시 미스
CPU가 요청한 데이터가 캐시 메모리에 존재한다면 Cash Hit 이라고 하고, 반대로 캐시 메모리에 존재하지 않는다면 Cash Miss 라고 한다.
캐시 배치 정책
- Direct Mapped Cache
- Fully Associative Cache
- Set Associative Cache
Direct Mapped Cache
- 가장 기본적인 캐시 배치 정책
- 주기억장치와 캐시에 대해서 N:1 방식(1:N 불가)을 적용해 저장 -> 즉, 하나의 캐시 주소에 여러 데이터 저장 가능
- ex) 메모리 공간이 32개 캐시 공간이 8개라면 각각의 캐시곤간에 메모리 주소 4를 할당한다.
- 주소가 tag, index, byte offset과 같은 주소로 구성되어있어서(찾는 규칙이 존재) 액세스 시간이 빠르다
- Conflict Miss가 발생할 수 있음
Fully Associative Chache
- 메모리 블록이 캐시에 어느곳에나 들어갈 수 있도록 하는 구조(찾는 규칙이 없다)
- 충돌이 나지 않아 캐시 미스율이 낮다
- 모든 주소를 확인해야 하기 때문에 시간이 오래걸린다.
- 구현이 복잡 비용이 높음 액세스 시간이 느림
Set Associative Cache
- 위 두가지 방식의 중간 형태 -> 캐시 미스율도 낮추고 액세스 시간도 높이고
- 캐시 블록을 여러개의 세트로 그룹화 해서 매핑
- 각 메모리 블록당 n개의 캐시 주소에 저장할 수 있도록 그룹화
캐시 교체 정책
캐시 메모리는 한정적이기때문에 효율적인 사용이 중요합니다. 때문에 어떤 정보를 오래 저장할지에 대한 부분이 중요합니다.
관련 용어
- Compulsory(cold) Miss : 처음 접근된 데이터 에서 발생하는 Miss
- Conflict Miss : 하나의 캐시 메모리 주소에 두개 이상의 데이터가 저장되어 발생하는 Miss
- DRAM의 정보를 캐시에 저장할때 다대일 방식으로 저장하게 됩니다. 그렇다면 여러개의 DRAM 주소가 캐시에 저장이 되게 되는데 이 때 새로운 데이터가 기존에 데이터와 충돌이 발생하고 이러한 문제점으로 발생하는 Miss 를 Conflict Miss 라고 합니다.
- Capacity Miss : 캐시 메모리 공간이 부족해서 발생하는 Miss
레지스터
레지스터란, CPU의 요청을 처리하는데 필요한 데이터를 일시적으로 저장하는 공간
여기까지 본다면 캐시랑 비슷하다
하지만, 캐시는 CPU 밖에 저장한다면 레지스터는 CPU 안에서 데이터를 저장한다.
주로 데이터의 연산 처리를 담당합니다.
- CPU에 직접 연결되어있기 때문에 연산속도가 빠르다
- 비싸다
- CPU에는 자체적으로 데이터를 저장하는 공간이 없기때문에 레지스터를 이용한다.
주소 할당
프로세스의 주소는 논리적 주소(가상메모리 공간 내의 주소)와 물리적 주소로 나눠집니다.
- 논리적 주소 : 가상 주소라고도 하며, CPU가 생성하는 주소이고, 프로세스마다 독립적으로 갖는다.
- 물리적 주소 : 프로세스가 실행되기 위해 실제로 메모리에 올라가는 위치
주소할당이란, 어떤 프로그램이 메모리의 어느 위치에, 어떤 물리적 주소에 할당될지 결정하는 과정을 의미합니다.
할당 시점에 따른 분류
- Compile Time Binding
- 프로세스의 물리적 주소가 컴파일할 때 컴파일러에 의해 할당됩니다.
- 컴파일 시점에 주소가 결정되기에, 실행 시 주소 변경이 불가합니다.
- 주소가 변경된다면 컴파일을 다시 실행해야한다.
- 논리적 주소와 물리적 주소가 동일합니다.
- ex) 정적 메서드, 정적 변수
- Load Time Binding
- 프로그램이 메모리에 로드 될때 주소 할당이 이뤄집니다.
- 프로그램 주소가 변경되어도 재컴파일 하지 않아도됩니다.
- 프로그램 실행시 주소 변경이 필요하다.
- ex) 동적 메서드, 동적 변수
- Excution(Run) Time Binding
- 프로그램이 실행할때 주소가 할당됩니다.
- 가장 유연한 방식
- 성능이 가장 안좋음
- ex) 동적 메모리 할당
메모리
메모리란, 프로그램 실행시 필요한 주소, 정보들을 저장하고 가져다가 사용할 수 있는 공간
각각의 프로세스는 독립된 메모리 공간을 갖습니다.
프로세스는 다른 프로세스나 운영체제의 메모리 공간에 접근할 수 없지만, 운영체제는 메모리 접근이 가능하여 관리한다.
멀티 프로그래밍 환경으로 변화하면서 메모리 관리 방법이 중요하다.
효율적인 메모리 사용 방법
- 동적 적재
- 프로그램 실행에 필요한 부분만 적재
- 모든 데이터를 사용하는 것이 아닌, 실행할 때 필요한 부분만 메모리에 적재합니다.
- 동적 연결
- 라이브러리 연결을 컴파일 시점이 아닌 실행 시점에 실시하는 것
- 스와핑(스왑 영역)
- 메모리에 적재되었으나 사용하지 않는 프로세스를 관리
- CPU할당이 끝난 프로세스를 보조기억 장치로 보내고 다른 프로세스를 불러오는 것
- 보조기억 장치로 보내는 과정(swap-out)
- 메모리로 프로세스를 불러오는 과정을 (swap-in)
메모리 단편화
메모리에 프로세스를 작은 조각으로 나눠서 적재할때의 남는 부분이 있지만 공간이 맞지 않아 할당이 불가능한 상황을 말합니다.
크게 두가지 종류로 나눠집니다.
내부 단편화
프로세스를 페이지로 분할해서 적재할때 물리 메모리를 나눈 프레임들중 마지막 프레임이 가득차지 않는 현상
외부 단편화
프로세스가 할당되고 사용이끝나고 반납되는 과정에서 남는 공간이 생기지만 다음 프로세스를 할당하지 못하는 현상
ex) 6GB를 할당하고 반납한후 그자리에 4GB를 할당 -> 2GB 남지만 다음 프로세스가 4GB로 할당 불가
해결 방법 : 압축(남는 공간 합치기 -> 작업 효율 좋지 않음)
메모리 관리 방법
단편화 상황을 줄이고 효율적인 Swapping을 통해 메모리를 관리하는 방법
연속 메모리 할당
프로세스를 연속적으로 할당하는 기법. 할당과 제거를 반복하면 외부 단편화 발생 가능
크게 두가지로 나눠진다
고정 분할 방식
- 시스템 생성 시 메모리가 이미 특정 크기와 고정된 파티션들로 연속적으로 분할되는 방식
- 균등 분할
- 모든 파티션 크기가 일정
- 프로세스 > 파티션 크기 : 오버레이 기법이 사용되어야 해서 부하 증가
오버레이 기법 : 프로세스를 모듈 단위로 나눠서 필요한 부분만 메모리에 할당
- 프로세스 < 파티션 크기 : 파티션에 맞지 않는 크기로 공간이 남게되고 내부 단편화 문제발생
- 비균등 분할
- 파티션의 크기가 일정하지 않음
- 잘 맞는 파티션에 할당하면 문제 해결 가능
원리가 단순하지만 효율적인 공간 운영이 안돼서 잘 사용하지 않는다
동적 분할 방식
- 필요한 크기만큼 메모리에 연속적으로 할당하는 방식
- 할당하고 회수하는 과정에서 외부 단편화 발생(압축, 통합 방식으로 해결가능 하지만 효율이 좋지않음)
- 외부 단편화를 줄이기 위한 방법
- 최초 적합(First Fit) : 가장 처음에 만나는 빈 메모리 할당
- 최적 적합(Best Fit) : 가장 크기 차이가 적은 곳에 할당
- 최악 적합(Worst Fit) : 가장 크기 차이가 큰 곳에 할당(할당하고 남은 공간에 다시 다른 프로세스 할당 가능 조건)
페이징 기법
프로세스들은 메모리에 연속적으로 할당되어야한다는 점은 없앤 기법.
논리 메모리는 페이지라고 불리는 고정된크기로 분할 하고 물리 메모리는 프레임이라고 불리는 고정된 크기로 분라한다.
MMU의 재배치 레지스터 방식을 이용해서 연속적인 메모리로 할당된 것 처럼 인식
프로세스가 순서대로 메모리에 저장되어 있지 않으므로 Page Table이라는 테이블에 어떤 page가 어느 frame에 들어있는지 저장한다.
장단점
- 연속해서 저장할 필요가 없기 때문에 외부 단편화를 해결 할 수 있습니다.
- 메모리를 분리해서 저장하기 때문에 내부 단편화 비중이 증가하게 됩니다.
- 내부 단편화를 줄이기 위해서 메모리를 더 잘게 분리하면 페이지 테이블의 크기가 증가하여 효율성이 감소하게됩니다.
- 이러한 단점을 효율적으로 해결하기 위해 TLB라고 하는 고속 하드웨어인 캐시를 사용합니다.
TLB(Translation Look-aisde Buffer)
- 메모리 주소 변환을 위한 별도의 캐시 메모리
- 캐시 메모리를 사용하기 때문에 속도가 빠릅니다.
- 하는 작업은 페이지 테이블과 유사합니다(논리 주소 -> 물리 주소).
- TLB에서 발견되지 않는다면 페이지 테이블을 탐색합니다.
페이지 교체 알고리즘
필요한 페이지가 메모리에 없을때 page-fault가 발생하고 OS가 필요한 필요한 페이지를 디스크(스왑영역)에서 물리 메모리로 로드 하게되는데, 이때 어떤 페이지가 교체 될 것인지를 결정하는 알고리즘입니다.
어떤 페이지가 교체될 것인지 선택하는 것은 성능에 영향을 끼치기에 page-fault를 줄일 수 있는 방향으로 선택합니다.
- FIFO
- 말 그대로 들어온 순서대로 교체합니다.
- 간단하지만 성능이 좋지 않습니다.
- OPT(Optimal - 최적의)
- 앞으로 오랫동안 사용하지 않을 페이지를 교체합니다.
- 앞으로 사용할 페이지를 알아야 하는 것은 거의 불가능 하기에 존재할 수 없습니다.
- LRU(Least Recently Used)
- 가장 오랫동안 사용되지 않은 페이지를 교체합니다.
- 많은 OS가 선택한 알고리즘 입니다.
- LFU(Least Frequently Used)
- MFU(Most Frequently Used)
- NRU(Not Recently Used)
- 이름 그대로 사용되지 않은 페이지를 교체합니다.
- LRU는 최근 사용 시간으로 구분하지만 NRU는 최근 사용 여부만 고려합니다.
세그멘테이션 기법
페이징 기법에서는 논리 메모리와 물리 메모리를 같은 크기로 분리하였다면, 세그멘테이션은 서로 다른 크기의 논리적 단위인 세그먼트로 분리합니다.
페이지와 동일하게 연속적으로 저장될 필요가 없고 세그먼트 테이블을 사용합니다.
크기가 다르기 때문에 세그먼트 테이블에는 limit(세그먼트 길이) 가 저장됩니다.
장단점
장점
- 논리적 단위로 관리할 수 있어서 효율적입니다.
- 서로 다른 크기들이 적재되고 제거되기때문에 외부 단편화가 발생할 수 있습니다.
메모리 풀 기법
필요한 메모리의 크기와 개수만큼 사용자가 직접 정해서 미리 할당 받고 필요할 때마다 사용하고 반납하는 기법
메모리의 할당과 해제가 빈번한 경우에 효과적이다.
특징
장점 :
- 필요한 공간을 할당받고 사용하기 때문에 외부 단편화가 발생하지 않습니다.
- 필요한 크기만큼 할당해놓기 때문에 내부 단편화가 발생하지 않습니다.
단점 :
- 단편화로 인한 메모리 낭비보다 메모리 풀을 사용해서 미리 만들어놓고 사용하지 않는 메모리양이 더 많다면 비효율적입니다.