Search
🤖

메모리 관리

논리적 메모리, 물리적 메모리

논리적 메모리 (= virtual address)

논리적 메모리는 독립적으로 가지고 있는 주소 공간이다.
각 프로세스마다 0번지 부터 시작한다.
CPU가 보는 주소는 logical address이다.

물리적 메모리

메모리에 실제 올라가는 위치

주소 바인딩

주소를 결정하는 과정.
프로그래머는 실제 메모리 주소로 호출하지 않고, 메소드 명, 변수 명, 패키지 명 등으로 특정 메모리 주소에 있는 값을 읽고 쓴다. 이를 symbolic address 라고 한다.
이런 코드가 컴파일 되면 실제 메모리에 할당될텐데, 이 메모리 할당과 위치를 확정하는 과정을 주소 바인딩이라고 부른다.
symbolic address → logical address → physical address
3가지 종류가 있다.

컴파일 타임 바인딩

물리적 메모리 주소(physical address)가 컴파일 시 알려짐
시작 위치 변경시 재컴파일
컴파일러는 절대 코드(absolute code, 주소값이 고정) 생성
현재의 컴퓨터 시스템에서 컴파일 타임 바인딩이 활용되지 않는다. 하나의 프로그램만 돌아가는 시스템이면 모를까.

로드 타임 바인딩

Loader의 책임하에 물리적 메모리 주소를 부여하는 방식
컴파일러가 재배치가능코드(relocatable code, 주소값이 가변)를 생성한 경우 가능
컴파일엔 논리주소만 결정되고, 실행시에 물리적인 메모리 주소가 결정된다. (논리 메모리에 특정 주소값을 더하는 방식으로 결정된다) 실행 중엔 변경되지 않는다.

런타임 바인딩

프로세스 수행이 시작된 이후에도 프로세스의 메모리 상 위치를 옮길 수 있음
CPU가 주소를 참조할 때 마다 binding을 점검 (address mapping table)
그때 그때 논리 주소를 가지고 물리 주소로 변환을 해줘야 하기 때문에, 하드웨어 지원이 필요함 (예. base and limit registers, MMU)
현재 대부분의 프로그램은 런타임 바인딩이다.
주소 바인딩 개략도

MMU (Mamory-Management Unit)

logical address를 physical address로 매핑해주는 하드웨어. 아래 설명은 메모리에 전체 프로세스가 올라간다는 것을 전제로 한다.

MMU Scheme

사용자 프로세스가 CPU에서 수행되며 생성해내는 모든 주소값에 대해 base register(=relocation register)의 값을 더한다.
유저 프로세스는 logical address만 다루며, physical에 대해선 알 필요도 없다.

Dynamic Relocation

원리는 base register와 limit register, 두 레지스터에 저장한 값으로 이루어진다. CPU가 프로세스의 논리주소를 요청하면, 해당 논리주소에 relocation register값을 더해 돌려준다.
3000의 크기를 가진 프로세스가 346번지 논리주소를 요청했을 때
base register = 접근할 수 있는 물리적 메모리 주소의 최소값 (프로세스 시작값)
limit register = 논리적 주소의 범위
limit register는 프로그램의 크기를 담고 있는 값으로, 해당 프로세스에 할당된 값이 아닌 다른 프로세스의 값을 요청할 수 없게 하기 위해 존재한다. 실수로든 혹은 악의적으로든, 요청한 논리주소 값이 base + limit 을 합친 값보다 크다면 trap(adressing error)이 발생한다.

Dynamic Loading

basic concept

파레토 법칙처럼, 프로그램 중 자주 사용되는 부분은 일부분이다. 나머지 대부분은 어쩌면 프로그램 실행동안 한번도 호출되지 않을(그러나 없어서는 안 될) 오류 처리 루틴 같은 것이다. 그리고 하드디스크와 달리 메모리는 비싸다. 이 두가지 사실이 만나 프로그램을 실행할 때 하드디스크에 있는 프로세스를 전부 메모리에 올리는 것이 아니라, 해당 루틴이 불려질 때 메모리에 로드해 놓는다는 개념인 다이나믹 로딩이 나오게 되었다.
이를 OS에서는 페이징 기법이라는 방식으로 구현해 놓았다. 유저 프로그램은 따로 다이나믹 로딩에 대해 신경쓰지 않아도 OS에서 알아서 해주지만, 프로그램적으로 처리가 가능하도록 라이브러리로 제공해주기도 한다.

Overlays?

overlays란, 메모리에 프로세스의 부분 중 실제 필요한 정보만을 올리는 것을 뜻하는 말이다. 다이나믹 로딩과 동일해보이지만, 역사적으로 프로그래머가 메모리가 무척 작던 시절 수작업으로 프로그래머가 구현하던 것을 일컬어 overalys라고 한다.
구분
overlays
dynamic loading
구현하는 주체
프로그래머가 수작업으로
OS가 직접 or 라이브러리 제공

Swapping

스왑핑은 프로세스를 일시적으로 메모리에서 backing store로 쫓아내는 것을 의미한다.

backing store

Swap Area라고 부르기도 한다. 디스크 영역에 있으며, 다수 사용자의 프로세스 이미지를 담을만큼 충분히 빠르고 큰 저장공간을 할당한다.

Swap In / Swap Out

중기 스케줄러(=swapper)가 swap out 시킬 프로세스를 선정한다.
우선순위 스케줄링 알고리즘에서 활용 될 때
우선순위가 낮은 프로세스를 swapped out 시킴
우선순위가 높은 프로세스를 메모리에 올려 놓음
컴파일 타임 바인딩 혹은 로드 타임 바인딩은 원래 메모리 위치로 swap in 해야함(비효율적), 실행시간 바인딩은 빈 메모리 영역 아무곳에나 올릴 수 있으므로 Swapping과 궁합이 잘 맞는다.
Swap time은 대부분 transfer time(swap되는 양에 비례하는 시간)이다.
페이징 시스템에선 프로세스의 일부(페이지)만 Swap In, Swap Out한다!

Dynamic Linking

Linking을 실행 시간까지 미루는 기법.
static linking
라이브러리가 실행파일 코드에 포함됨
실행 파일의 크기가 커짐
동일한 라이브러리(예. printf 함수의 라이브러리 코드)를 각각의 프로세스가 메모리에 올리므로 메모리 낭비
dynamic linking
라이브러리가 실행시 연결(link)됨
라이브러리 호출 부분에 라이브러리 루틴의 위치를 찾기 위한 stub이라는 작은 코드를 둠
라이브러리가 이미 메모리에 있으면 그 루틴의 주소로 가고 없으면 디스크에서 읽어와 메모리에 적재
운영체제의 도움이 필요
이때 활용되는 라이브러리를 리눅스에선 Shared Object, 윈도우에선 DLL 이라고 표현한다.

물리 메모리 할당

메모리는 일반적으로 두 영역으로 나누어 사용한다.
1.
OS 상주 영역
interrupt vector와 함께 낮은 주소 영역을 사용한다.
2.
사용자 프로세스 영역
OS 상주영역보다 높은 주소 영역을 사용한다.

사용자 프로세스의 할당 방법

1.
Contiguous allocation
a.
각각의 프로세스가 메모리의 연속적인 공간에 적재되도록 하는 것
Fixed Partition allocation - 고정 분할 방식
프로그램이 올라올 메모리공간을 미리 분할해 놓는다.
사용할 수 없는 메모리 - 조각문제
외부 조각(모든 프로그램이 분할 크기 보다 클 때)
내부조각(프로그램이 분할 크기보다 작을 때)이 발생한다.
Variable Partition allocation - 가변 분할 방식
고정 분할 방식의 문제점을 수정하고자 등장
그러나 프로그램이 시작되고 종료되는 와중 발생하는 외부조각은 해결할 수 없다. 이렇게 가변분할 방식에서 발생한 빈 공간을 Hole이라고 부른다.
Hole을 가장 잘 처리할 수 있는 알고리즘에 대해선 Dynamic Storage-Allocation Problem을 살펴보라.
2.
Noncontiguous allocation - 현대 프로그램에서 활용!
a.
하나의 프로세스가 메모리의 여려 영역에 분산되어 올라갈 수 있음
paging
메모리 공간을 page frame단위로 분할한 후, 프로세스도 page frame 단위로 쪼개어 올려놓는다. (hole 문제 해결)
어드레스 바인딩이 복잡해진다 (페이지마다 base register가 달라진다)
segmentation
코드 영역, 데이터 영역, 스택 영역와 같이, 의미 단위로 영역을 분할하여 다른 영역에 올리는 방식.
paged segmentation
paging과 segmentation의 결합. segment 마다 paging을 하는 방식이다.

페이징 기법

페이지 테이블

논리 주소를 페이지로 잘라 실제 메모리에 올려놓기 위해, 페이지 테이블이 운용된다.
페이지 테이블
페이지 테이블은 main memory에 상주한다.
Page-table base register(PTBR)이 page table의 주소(base 값)를 가지고 있다.
Page-table length register(PTLR)이 테이블 크기(limit 값)를 보관한다.
페이지 테이블의 존재로 인해 메모리 접근연산에는 2번의 메모리 접근이 필요하다. (table 한번, 실제 데이터 한번)
속도 향상을 위해 associative register 혹은 translation look-aside buffer(TLB) 라 불리는 고속의 lookup hardware cache가 활용된다.
TLB의 구조

5단계 페이지 테이블

basic concept

논리 메모리 주소를 몇비트까지 허용하느냐에 따라 가용한 논리 메모리 주소가 달라진다. 현대의 컴퓨터는 대개 64bit address를 쓰는데, 이는 16엑사 바이트이다. (참고-마이크로 소프트 문서) 페이지는 각 4KB이다. 16엑사 바이트를 4KB로 나누면, 4페타(10의 15승)개인데 페이지 테이블의 한 엔트리가 4B 정도를 차지하니.. 한 프로세스당 16페타바이트(!)의 페이지 테이블을 할당해야 한다.
그러나 실제로는 이론상 가능한 영역에 비해 매우 적은 가상 메모리만 활용되므로, 필요한 만큼의 페이지테이블만 만들 필요가 있다.
이를 위해 페이지 테이블도 페이지(4kb)단위로 쪼개고, 바깥 테이블을 만들어 안쪽 페이지 테이블의 페이지 주소를 가지고 있게 구현하였다. 안쪽 페이지 테이블이 비어있다면, 값을 null로 할당해 비워둠으로써 공간을 null null하게 사용한다.(하하!)

페이지 테이블의 비트값들

페이지 테이블의 엔트리에는 추가적인 비트가 있다.
1.
Protection bit
a.
페이지에 대한 접근 권한(read / write / read-only)
2.
Valid-invalid bit
a.
valid는 해당 주소의 frame에 그 프로세스를 구성하는 유효한 내용이 있음을 뜻함 (접근 허용)
b.
invalid는 해당 주소의 frame에 유효한 내용이 없을을 뜻함 (메모리에 없으므로 접근이 불가능하다)
i.
프로세스가 그 주소 부분을 사용하지 않는 경우
ii.
해당 페이지가 메모리에 올라와 있지 않고 swap area에 있는 경우

Inverted Page Table Architecture

페이지 테이블이 메모리를 효율적으로 사용할 수 있게 해주었지만, 페이지 테이블 자체가 차지하는 메모리가 많아지게 되었다. 시간적인 이점을 포기하고 공간적인 이점을 얻기위한 아키텍쳐로, 프로세스당 페이지 테이블이 아닌 시스템 전체에서 하나의 페이지 테이블을 가지고 있도록 구현한 것이 Inverted Page Table이다.
페이지 테이블에서 각 페이지 테이블 엔트리는, 각각의 물리적 메모리의 page frame이 담고 있는 내용을 표시한다.
검색할 때 마다 테이블 전체를 탐색해야 하므로 검색 시간이 오래 걸리는 단점이 있고, associative register를 사용하여 병렬 검색하는 방식으로 조치할 수 있다.
pid와 페이지 번호의 조합으로 물리 저장공간을 찾는다.

Shared Pages Example

코드 중에선 함께 쓸 수 있는 영역이 있다. 이 것을 shared code라고 하는 데, read-only로 구현하여 프로세스 간에 하나의 코드만 메모리에 올려도 충분할 것이다. (예. 텍스트 편집기, 컴파일러, 윈도우 시스템)
모든 프로세스가 공유해야할 코드이므로 모든 프로세스의 logical address space에서 동일한 위치에 있어야 한다.

Segmentation Architecture

메모리를 논리단위로 구분하여 저장하는 것이다. code, stack, data 같은 식으로 나눌 수 도 있고, 각 메서드마다 공간을 할당하는 식으로도 작성할 수 있다.
segmentation 아키텍처에선 Logical address를 {segment-number, offset}의 조합으로 표현한다.
Segment table
각 엔트리는 base와 limit 값을 가지고 있다.
base - 세그먼트의 물리적 시작 주소
limit - 세그먼트의 길이
Segment-table base register(STBR)
물리적 메모리에서의 segment table의 위치
Segment-table length register(STLR)
프로그램이 사용하는 segment의 수
프로그램이 가진 STLR보다 segment number가 크면 트랩이 발생한다.

Segmentation에서 사용하는 비트

각 세그먼트 별로 Protection bit가 있다.
Valid bit 유효성 비트
Read/Write/Execution 권한 비트

Segmentation 기법의 장단점

장점

segment는 의미 단위이기 때문에 공유와 보안에 있어 paging보다 훨씬 효과적이다.

단점

Segment의 길이가 동일하지 않으므로 가변분할 방식과 동일한 문제점들이 발생한다. (외부 조각 발생)
page와 segment의 비교

Segments with Paging

Segment 와 paging 방식을 혼용한 방식. 두 가지 방법의 장점을 모두 누릴 수 있다. (공유와 보안, 메모리의 효율적 활용)
순수한 Segmentation과의 차이점
segment-table entry가 segment의 base address를 가지고 있는 것이 아니라 segment를 구성하는 page table의 base address를 가지고 있음.

레퍼런스