Memory Abstraction
Memory Abstraction, 즉 메모리 추상화는 하드웨어의 복잡성을 숨기고 응용 어플리케이션이나 운영 체제에게 간단하고 일관된 메모리 인터페이스를 제공하는 목적으로 활용되는 테크닉이다.
만약 메모리 추상화가 없다면 각 프로세스들의 주소 공간을 관리하는 과정에 매우 복잡해진다.
예를 들어, 다음과 같이 Physical Memory에 여러 Process가 실행중인 상황을 살펴보자.
각 Process A, B, C는 Physical Memory에서 다른 주소 공간에 위치하고 있다. 따라서 각 Process들이 시작되는 메모리 주소가 다를 것임을 알 수 있다.
하지만 Memory Abstraction을 위해 Virtual Memory를 구현하게 되면, 다음과 같은 구조로 변하게 된다.
즉 Process가 실제로 Physical Memory의 어느 부분에 위치하는지와 관계 없이 주소 공간이 0부터 시작하게 된다.
이렇게 되면 사용자의 입장에서는 메모리 공간의 할당과 관련하여 수동으로 관리하거나 고려할 필요가 사라지고, 필요한 작업만을 편리하게 수행할 수 있다.
이 외에도 메모리 추상을 활용하면 메모리 공유를 쉽게하고, 낭비되는 메모리 공간을 줄이며 보안을 강화할 수 있는 등 다양한 장점이 있다.
Address Translation
Address Translation은 Virtual Memory 기술의 구현을 위해 필요한 기능에 해당한다.
process의 virtual address를 바탕으로 `MMU(Memory Management Unit)`가
이를 physical address로 translate한 후 실제 메모리에 접근하게 된다.
이러한 Translation에는 여러 방식이 존재하는데, 대표적으로 `base and bound`, `segmentation`, `paging`이 있다.
Base and Bound
가장 단순한 Address Translation 방법이다.
단순히 base 값을 Virtual Memory에 더해서 Physical memory로 변환하는 과정으로, bound 체크를 통해 변한된 메모리가 해당 범위를 벗어날 경우 exception을 발생시킨다.
Base and Bound 방식으로 메모리 할당을 진행할 경우, 반드시 연속된 공간을 사용하기 때문에 `contiguous allocation`이 수행된다.
Segmentation
Segmentation은 Base and Bound 방식을 개선시킨 방법이다.
Segment Table을 두고 base와 bound 값을 배열로 가지고 있다.
그림에서 보면 base-bound-access 정보를 담은 데이터가 총 4칸 존재하는데 이는 메모리 공간을 구성하는 Code, Data, Heap, Stack에 해당한다.
Segmentation의 장점은 하나의 프로세스를 구성하는 메모리가 전부 연속해서 존재하지 않아도 된다는 점이다.
Base and Bound 방식의 경우 메모리 번역이 구성 요소와 관계 없이 단순 덧셈으로 이루어진다.
이는 곧 physical memory에서 code-data-heap-stack이 연속으로 존재해야 한다는 것을 의미하기 때문에 이 네 공간을 더한 크기 만큼의 연속적인 공간이 필수적으로 요구된다.
하지만 Segmentation의 경우 각 메모리 구성 요소마다 다른 base를 사용하여 Translation을 진행하고, 따라서 Physical Memory에서 Code, Data, Heap, Stack이 분리되어 존재할 수 있어 메모리 공간을 효율적으로 사용할 수 있다. 즉 base and bound에 비해 External Fragmentation 문제가 덜하다. (하지만 여전히 External Fragmentation 문제는 존재함)
또한 Segmentation의 경우 table의 access 정보를 통해 각 영역별로 Read-Write 권한을 분리할 수 있다는 장점이 있다.
이 Segment table은 크기가 매우 작기 때문에 CPU의 Register에 저장된다.
Paging
Paging은 memory를 특정 크기로 잘라 관리하는 방식이다.
Segmentation에서 segment의 크기가 될 수 있는 값이 매우 자유롭기 때문에, Address Translation을 진행하는 과정에서 Physical memory 영역에서 할당 공간이 겹치는 등의 문제가 발생하기 쉽고, 이를 관리하는 것이 매우 어렵다.
이 문제를 해결하기 위한 방식이 Paging으로 Virtual Memory에서의 단위는 page, Physical Memory에서의 단위는 page frame을 사용한다.
Translation 과정은 아래와 같다.
1. CPU가 virtual address를 MMU로 보내면, MMU는 이를 VPN(Virtual Page Number)과 VPO(Virtual Page Offset)로 파싱한다.
2. Page Table에 VPN으로 접근하여 PPN(Physical Page Number)을 얻는다.
3. PPN과 VPO를 합쳐 physical address로 translation한다.
Paging을 이용하면 external fragmentation을 완전히 방지할 수 있으나 internal fragmentation이 발생한다는 단점이 있다.
또한 Paging 기법에서 주소 변환을 위해서는 반드시 Page Table을 참조해야하는데, Page Table은 cache나 register에 올리기에는 크기가 너무 크다는 문제점이 있다. 따라서 이를 Physical Memory에 위치시키는데, 따라서 모든 메모리 접근 연상네는 2번의 memory access가 필요하게된다.
이러한 문제를 보완하기 위해 TLB(Translation look-aside buffer)를 사용하기도 한다.
Multilevel Paging
사용중인 컴퓨터의 logical address가 32bit이고, page size를 4KB라고 가정하자.
logical address가 32bit라는 것은 각 프로세스가 가질 수 있는 메모리의 공간이 $2^{32}$Byte라는 것을 의미한다.
따라서 각 프로세스 당 page는 $2^{30}$ 개가 된다. 이 $2^{30}$의 페이지를 모두 담는 page table을 프로세스마다 가져야 하므로 이는 매우 큰 메모리 overhead로 작용한다.
이를 해결하기 위해 Multilevel Paging을 사용한다.
위 그림으로 예를 들면, level 1 page table entry에서 얻은 값을 이용해 level 2 page table을 선택하고
level 2 page table entry의 값을 통해 level 3 table table을 선택한다.
각 테이블에서 어떤 엔트리를 고를 것인지는 virtual address에서 잘라낸 index1, index2, index3의 값을 사용하게된다.
이렇게 Multilevel Paging을 사용하는 경우 Level 1 Page는 index1의 크기만큼 모두 할당이 진행되지만,
Level 2 Page Table부터는 필요한 경우에만 Table이 생성되고, 초기에 모두 만들어두는 작업을 수행하지 않는다.
실제 프로세스에서 대부분의 페이지는 사용되지 않기 때문에, 이러한 Multilevel Paging 방법으로 많은 공간적인 이점을 가져갈 수 있다.
Inverted Page Table
inverted page table은 기존의 page table이 process의 page 개수만큼 엔트리를 가지면서,
프로세스 마다 page table이 존재해야함으로 인해 발생하는 Space Overhead를 줄이기 위한 방법이다.
inverted page table은 프로세스 개수와 관계 없이 딱 하나의 page table만 존재하고
physical memory의 page frame 개수만큼 page table entry가 존재한다.
다만 이 방법은 pid와 p가 일치하는 entry를 찾고, 해당 entry의 index를 이용해서 page frame의 위치를 찾는 방법이기 때문에 모든 엔트리를 선형 탐색해야한다는 단점이 있다.
Fill on Demand
Paging 방식을 사용하면 구현할 수 있는 기능으로,
프로그램 실행 시 필요한 부분만 Memory에 올리는 방식을 말한다.
일반적으로 프로그램을 실행하면 해당 프로그램을 실행하는데 필요한 모든 영역을 Memory에 올린다.
하지만 Physical Memory 공간은 한정되어 있기 때문에, 이렇게 하면 많은 프로그램을 동시에 실행하기 힘들 것이다.
Fill on Demand 방식을 사용하면 각 프로그램에서 실행할 부분만을 Memory에 올리기 때문에 더 많은 프로그램을 동시에 실행시킬 수 있다.
Fill on Demand의 동작 방식은 아래와 같다.
1. 프로그램이 실행된 직후에는 physical memory에는 아무런 부분도 할당되지 않는다. 따라서 Page Table Entry에 대한 접근이 모두 실패할 것이다.
2. Page Table Entry에 대한 접근이 실패하면 page fault가 발생한다.
3. Page fault 발생 시 disk로부터 해당 page를 가져오고, Page Table을 업데이트 한다.
'OS' 카테고리의 다른 글
[OS] 9. File System (0) | 2023.10.08 |
---|---|
[OS] 8. Virtual Memory (0) | 2023.10.03 |
[OS] 4. Process Scheduling (0) | 2023.10.02 |
[OS] 6.Deadlock (0) | 2023.09.30 |
[OS] 5. Synchronization(동기화) (0) | 2023.09.21 |