배경
메모리의 구성
- 각각의 주소를 가지고 있는 바이트의 배열
- CPU는 메모리로부터 명령어를 패치하거나, 저장할 수 있다.
메모리 공간
프로세스는 각자의 메모리 공간을 가지고 있다. 즉, 프로세스별로 독립된 메모리 공간을 가지고 있어야 한다는 뜻이다. 메모리 보호를 위해 base register와 limit register를 가진다.
메모리 보호는 CPU 하드웨어가 유저모드에서 주소를 생성해낼 때마다 매번 비교를 하며 이루어진다. 새로운 주소가 base register보다 크거나 같고, base+limit register보다 작을 때만 정상적으로 할당할 수 있게끔 한다.
논리 주소 공간: 유저 프로그램에 의해 만들어지는 메모리 주소
물리 주소 공간: 논리 주소 공간에 매핑되는 실제 데이터가 저장되는 메모리 주소
MMU: 논리 주소를 물리 주소에 매핑시키는 하드웨어 장치.
Dynamic Loading
전체 프로그램을 한 번에 로딩하면 부하가 너무 크기 때문에 필요할 때만 루틴을 로딩하여 메모리 공간을 효율적으로 사용하는 방법.
DLL(Dynamically Linked Libraries): 프로그램이 돌아가고 있는 도중에 필요한 라이브러리를 링킹해주는 것.
Contiguous Memory Allocation
프로세스에 메모리를 할당해주어야 하는데, 연속 메모리 할당은 프로그램을 통째로 올리는 방법으로, 이러한 메모리는 운영체제나 유저 프로세스가 사용하게 된다.
Memory Protection
연속 메모리 할당같은 경우는 프로세스를 통째로 할당하기 때문에 메모리를 보호하는 것이 간단하다. relocation register와 limit register만을 이용해 메모리를 보호할 수 있다.
Memory Allocation
메모리를 할당하는 방법에는 또 여러가지 경우가 있는데, 메모리 안에 변동가능한 사이즈의 파티션에 프로세스를 할당하는 것이다. 이렇게 되면 프로세스가 메모리에 올라갔다 내려가면서 구멍(free hole)이 생기게 되는데, 이를 잘 관리하는 것이 중요하다.
이러한 free hole에 새로운 프로세스를 할당하는 방법에는 크게 3가지가 있다.
- First-Fit: Linked List를 처음부터 살펴보면서 할당가능하다면 바로 할당해준다.
- Best-Fit: 우선순위 큐를 이용하여 들어갈 수 있는 가장 작은 hole에 할당한다.
- Worst-Fit: 가장 큰 hole에 먼저 순차적으로 할당해준다.
Fragmentation
메모리 공간이 작은 조각으로 나뉘어져 사용가능한 메모리가 충분히 존재하지만 할당이 불가능한 상태를 메모리 단편화라고 한다.
내부 단편화
메모리를 할당할 때 프로세스가 필요한 메모리보다 더 큰 메모리가 할당되어 메모리 공간이 낭비되는 현상.
외부 단편화
충분한 공간이 있지만 프로세스가 필요로 하는 메모리보다 크기가 작아서 사용할 수 없는 현상. 전체적으로 보면 공간은 남아있지만 프로세스를 쪼개서 할당할 수는 없기 때문에 이러한 단편화 문제가 생긴다.
페이징
프로세스의 물리적 주소를 연속적이지 않게 쪼개서 관리하는 것. 이것은 외부 단편화를 막고 쪼개진 메모리 덩어리를 압축할 필요도 없다.
- frames: 물리 메모리를 고정 사이즈로 쪼갠 블록.
- pages: 논리 메모리를 같은 사이즈의 블록으로 쪼갠 것.
우리는 논리 메모리 주소만 생각하여 프로그래밍을 하고 실제 물리 메모리와의 매핑은 OS가 알아서 해준다.
따라서 실제 CPU가 생성하는 메모리 주소는 아래와 같이 page number와 page offset으로 이루어져 있고, 이것이 물리적 주소와 매핑되는 것이다.
논리 주소를 통해 매핑되려면 page table을 참고하여 물리 주소로 변환해야 한다. 아래의 그림과 같은 과정으로 실제 주소를 찾아간다.
page number와 page offset을 계산할 때 논리 주소 공간이 2m이고 page size가 2n라고 한다면, page number는 m-n, page offset은 n이다.
CPU가 문맥 교환을 할 때 page table 또한 같이 문맥 교환이 일어나야 한다. 하지만 크롬같이 거대한 프로그램에서 이런 상황은 오버헤드가 굉장히 큰 작업일 수 있다.
TLB
Shared Pages
페이지를 이용하면 공통의 코드를 공유할 수 있어 훨씬 효율적이다. 페이지를 이용하면 Reentrant code를 공유하여 메모리 공간을 절약할 수 있다. 예를 들어 libc 라이브러리를 모든 프로세스가 카피본을 가지고 있다면 쓸데없이 공간을 너무 잡아먹는다. 이를 필요로 하는 프로세스를 공유하여 이러한 메모리 누수를 막을 수 있다.
Reentrant code: 프로그램 실행 중에 스스로 변경되지 않는 코드.
Page Table의 구조
논리 주소 공간이 너무 커지면 페이지 테이블 또한 엄청나게 커질 수 있다. 이를 효과적으로 관리하기 위한 페이지 테이블의 여러 가지 구조가 있다.
Hierarchica Paging
페이지 테이블이 너무 커지면 커진 페이지 테이블의 페이지 테이블을 또 만들자는 개념이다.
Hashed Page Tables
데이터를 넣고 뺄 때 가장 효율적인 자료구조가 해시이다. 해시 자료구조를 이용하여 페이지 테이블을 구성한 것이 Hashed Page Tables이다.
Inverted Page Tables
pid를 가지고 페이지 테이블을 구성하는 방법을 Inverted Page Tables이라 한다.
Swapping
swapping: 실제 물리적 공간보다 프로그램의 용량이 더 크더라도 프로그램이 동작할 수 있게 해준다. 프로세스에서 필요한 부분만큼만 메모리에 올리고 필요하지 않다면 다시 메모리에서 내리는 방식으로 아주 큰 프로그램도 동작할 수 있게 해준다.
swap in: 프로세스를 메모리에 올리는 것.
swap out: 프로세스를 메모리에서 내리는 것. backing store.
Standard Swapping
프로세스 전체를 swapping 시키는 방법으로 아무래도 전체 프로세스를 스와핑하는 비용이 너무 많이 든다.
Swapping with Paging
프로세스의 페이지를 swapping 시키는 방법으로 현재 대부분의 시스템이 동작하는 방식이다. 전체 프로세스가 아닌 프로세스의 페이지 단위를 swapping 시키기 때문에 훨씬 효율적이다. 우리가 페이징이라 부르는 것은 이 swapping with paging을 의미하는 것으로, 여기서는 page in, page out이라 한다.
'CS 지식 > 운영체제' 카테고리의 다른 글
운영체제 Ch11~15 - 스토리지 관리 (0) | 2022.01.07 |
---|---|
운영체제 Ch10 - 가상 메모리 (0) | 2022.01.06 |
운영체제 Ch8 - 데드락 (0) | 2022.01.03 |
운영체제 Ch7 - 동기화 문제의 예시 (0) | 2021.12.13 |
운영체제 Ch6 - 프로세스 동기화(2) (0) | 2021.12.12 |