메모리에 대한 내용은 핀토스 때 다루었으나,
전체적인 큰 그림을 다시 한번 잡고 싶어서 스터디를 준비하며 다시 정리해본다.
1. 메인메모리
메인메모리와 레지스터는 CPU가 직접 접근할 수 있는 저장장치이다. 레지스터는 일반적으로 CPU의 one cycle에 CPU가 도달할 수 있지만, 메모리는 메모리 버스를 통한 데이터의 교환으로 여러 사이클이 소모된다. 속도적인 측면을 개선하고자 하드웨어의 일종인 cache가 고안되었다. 또한 OS를 유저프로그램의 접근으로부터 보호한다던가, 프로그램 별로 서로의 영역을 침범하지 않도록 하기 위해 하드웨어가 발명되었는데 대표적으로 base register와 limit register가 있다.
메모리 공간의 분리 (유저영역과 커널영역)
유저 메모리 공간과 OS 메모리 공간은 분리되어있다. 각 공간을 보호하기 위해 2개의 레지스터를 사용하는데 위에서 말한 base register와 limit register이다. base register를 통해서 해당 프로세스의 가장 아래의 물리 주소를 가질 수 있고, limit register를 통해서 해당 프로세스의 범위를 표시하고 있다. OS만이 커널 모드에서 base register와 limit register를 조작할 수 있다.
연속 메모리 할당( Contiguous Memory Allocation )
각 프로세스를 "통째로" 올리는 것을 연속메모리할당이라고 한다. 각 프로세스는 서로의 영역을 침범하지 않아야하는데, 여기서도 relocation register (= base register)와 limit register가 쓰인다. 메모리를 할당시 유한한 메모리의 범위를 어떻게 사용해야할지에 대한 고민이 생기는데, 여기서 동적 메모리 할당에 대한 개념이 나온다. 즉 블록의 크기가 정해져 있는 상황에서 유한한 가용공간을 가진 메모리에 어떻게 하면 효과적으로 메모리를 할당할 것이냐에 대한 문제이다.
최초 적합(first-fit)은 사용 가능한 첫번째 가용 공간을 할당한다.
최적 적합(best-fit)은 사용 가능한 공간 중 가장 작은 것을 택한다.
최악 적합(worst-fit)은 가장 큰 가용 공간을 택한다.
일반적으로 first-fit과 best-fit이 worst-fit보다 시간을 줄여주고 공간 활용을 늘려준다.
외부단편화 발생
하지만 이러한 동적 메모리 할당은 외부단편화를 초래한다. 메모리를 할당하고 free 시키는 과정에서 다수의 hole이 생기는데, 이러한 hole들이 곳곳에 산재하여 있기 때문에 가용가능한 메모리의 크기는 크나, 막상 프로세스를 올리려면 올릴 수 없는 상황이 발생하는 것이다.
해결방안으로는,
1. 물리메모리를 고정된 블록단위로 쪼개고 프로세스에 할당한다. but 내부 단편화의 문제점이 있다.
2. 압축기법으로 사용하는 메모리를 한 쪽으로 몰고 free한 공간을 다른 한쪽으로 모는 것. but 비용이 크고, 런타임에 동작하도록 구현필요
3. 프로세스를 연속적이 아니더라도 올릴 수 있게 만드는 것 => 페이징 기법
2. 페이징
페이징은 외부단편화를 줄이고, compaction의 필요성에 따라 대두되었다.
동작방법은 physical memory를 frame으로 불리는 fixed-size로 쪼개고, logical memory를 page로 해서 똑같은 사이즈로 쪼갠다.
logical address는 page number와 page offset을 가진다.
페이지의 사이즈는 컴퓨터 아키텍처에 따라 다른데 보통 2의 n승이며, 4KB ~ 2GB까지 다양하다.
CPU는 페이지 테이블과 offset을 활용하여 logical address를 통해서 physical memory로 접근할 수 있다.
TLB (translation look-aside buffer)
페이징 기법을 도와주는 하나의 하드웨어를 살펴보자.
이 하드웨어는 캐시메모리로서 캐싱을 통해 페이지 테이블에 도달하는 시간을 줄여준다.
하지만 캐시이므로 정보 저장이 제한되며,
원하는 physical address에 대한 정보가 올라와있으면 TLB hit, 그렇지 않으면 TLB miss가 뜬다.
3. Segmentation
프로그램은 의미 단위인 여러개의 Segment로 구성되어 있고,
작게는 프로그램을 구성하는 함수 하나하나를 세그먼트로 정의하기도 한다.
세그먼트는 페이징과 같은 것 같으면서도 다르다.
Segment Table
각 테이블은 base와 limit을 가진다. 페이징 기법과 비슷하고 base를 통해서는 시작점을, limit을 가지고는 해당 세그먼트의 크기를 나타낸다. 여기서 페이징과 조금 다른 점은 아래 그림에서 d(오프셋)이 페이징은 고정되어 있으나, segment는 변동된다는 점, 또한 limit의 크기도 바뀔 수 있다는 점이다. Segment-table base register (STBR)을 통해서 물리 메모리에서의 segment table의 위치를 찾아보거나,
Segment-table length register (STLR)에서 프로그램이 사용하는 segment의 수를 알아낼 수도 있다.
Segment의 몇가지 특징으로는
Allocation : segment의 길이가 동일하지 않으므로 가변분할 방식에서와 동일한 문제점들이 발생한다.(단편화 문제)
Protection : 각 segment 별로 protection bit가 있고 유효비트 혹은 권한(Read/Write/Execution)비트를 가진다.
Sharing : segment가 의미 단위이기 때문에 공유나 보안에 있어서는 페이징보다 오히려 효율적이다.
4. Swapping
멀티프로그래밍을 위해 메인메모리와 디스크 사이에서 프로세스의 페이지를 올렸다가 내렸다가 하는 것이다. 기존 UNIX 운영체제에서는 프로세스를 한번에 올리는 기법을 사용하였다. 하지만 현재의 Windows와 Linux에서는 개별 페이지들을 올리고, 현대의 대부분의 운영체제가 해당 기술을 사용하고 있다.
[참고]
- Operating System Concepts, 10th Edition (공룡책)
- 반효경 [운영체제] 20. Memory Management 3
'Study > Computer' 카테고리의 다른 글
[OS] Blocking, Non-blocking, Sync, Async 개념 (굳이 4등분?) (2) | 2023.03.15 |
---|---|
[OS] 스케쥴러와 CPU 스케쥴링 (0) | 2023.03.12 |
[기초] RESTful API란 무엇일까? (0) | 2023.03.01 |
[기초] 2의 보수에 대해 알아보자! (2) | 2023.02.15 |
크롬 개발자도구 알아보기 (0) | 2023.02.09 |