지난 글에서까지 메모리 관리에 대한 공부를 해보았습니다. 메모리 관리의 핵심은 다중 프로그래밍을 실현하기 위해 메모리에 많은 프로세스들을 동시에 유지할 수 있도록 하는 것입니다. 하지만 메인 메모리를 공부하면서 공부했던 방식은 모두 프로세스가 실행되기 위해 메모리로 올라와야 한다는 것을 전제로 합니다. 하지만 가상 메모리(Virtual Memory)를 사용하면 프로세스 전체가 다 메모리로 올라오지 않아도 실행이 가능합니다.
1. 가상메모리?
가상 메모리를 이용하면 프로그램이 실제 물리 메모리보다 큰 메모리 공간을 요구하더라도 사용이 가능하다는 장점이 있습니다. 가상 메모리는 물리 메모리로부터 사용자 관점의 논리 메모리를 분리시켜 메인 메모리를 균일한 크기의 저장 공간으로 구성된 엄청나게 큰 배열로 추상화시켜 줍니다. 말이 조금 어렵지만, 뒤에서 계속 공부하다가 보면 이해가 되실 것이라고 믿습니다.
기본적인 아이디어는 이러합니다. 명령어(instruction)는 반드시 메모리에서 실행되어야 하지만, 전체 프로그램이 지금 당장 필요한 것은 아닙니다. 그리고 만일 전체 프로그램이 다 필요하다 하더라도, 이 모든 프로그램이 동시에 필요한 것 역시 아닙니다. 그래서 프로그램을 부분적으로 메모리에 적재할 수 있다면 다음과 같은 이득을 얻을 수 있습니다.
1. 프로그램은 전체 물리 메모리 크기에 제약을 받을 필요가 없습니다. (조금씩 불러오면 되기 때문에)
2. 동시에 더 많은 프로그램이 실행될 수 있습니다. (각각의 프로그램들이 더 작은 메모리 공간을 차지하기 때문에) 이를 통해 효율적인 자원의 이용이 가능합니다.
3. 모든 프로그램을 메모리에 올리고 내리는 것보다 훨씬 빠르게 수행이 가능합니다.
이렇게 하면 사용자가 느끼기에는 정말 많은 프로그램이 메모리에 적재되어 있는 것으로 느낄 수 있습니다. 이처럼 작은 메모리로도 충분히 큰 가상 주소 공간을 프로그래머에게 제공할 수 있습니다.
2. 요구 페이징(Demand Paging)
가상 메모리를 구현함에 있어서 가장 중요한 개념이 바로 이 요구 페이징입니다. 앞에서 살펴봤던 바와 같이 모든 프로그램이 메모리에 적재되어 있을 필요가 없기 때문에, 페이지들이 실제로 실행될 때(요구될 때) 메모리에 적재하여 사용하는 방법을 요구 페이징이라고 합니다. 그리고 요구 페이징을 수행할 때 페이지들을 관리해 주는 역할은 페이저(Pager)가 맡게 됩니다.
페이저는 프로세스가 디스크에서 메모리로 올라올 때 어떤 페이지들이 필요로 되어지는 지를 파악하여 해당 페이저들만 가져옵니다. 이를 위해서는 메모리로 올라온 페이지들과 디스크에 남아있는 페이지들을 구분을 할 수 있는 방법이 있어야겠죠? 여기서 우리가 앞에서 공부했던 페이지 테이블의 valid bit를 사용합니다. Valid 하다면 현재 메모리로 적재되어 접근이 가능한 상태이고, invalid 한 상태라면 디스크에 남아있는 페이지이거나 아예 유효하지 않은 페이지라는 뜻입니다.
그렇다면 프로세스가 원하는 페이지가 메모리가 아닌 디스크에 존재하여 invalid한 상태라면 어떻게 해야 할까요? 이 상황에서는 Page Fault (페이지 부재)가 발생합니다. 페이지 부재가 일어나면 아래의 그림과 같은 과정을 통해 해결을 해주게 됩니다.
3. 페이지 교체(Page Replacement)
다중 프로그래밍이 늘어나면서 한 번에 실행되는 프로그램이 늘어나고 그렇게 되면 결국 모든 페이지가 사용되고 있는 상태가 될 수 있습니다. 다시 말해 물리 메모리에 남는 프레임이 하나도 없을 때는 어떻게 해야 할까요? 이때 바로 페이지 교체가 일어납니다.
페이지 교체의 기본적인 순서는 다음과 같습니다.
1. 디스크에서 요구되는 페이지의 위치를 찾는다.
2. 물리 메모리에서 비어있는 프레임을 찾는다. 만약 비어있는 프레임이 있다면 그냥 사용하면 되지만 만일 하나도 없다면, 페이지 교체 알고리즘을 통해 어떤 프레임을 선택하여 해당 프레임을 디스크로 돌려보내어 빈 프레임으로 만든다.
3. 이렇게 만든 빈 프레임에 원하는 페이지를 넣는다. 그리고 페이지 테이블을 최신화해준다.
이 때 물리 메모리에서 선택되어 디스크로 돌아가게 되는 프레임을 victim frame이라고 합니다. 이러한 페이지 교체가 일어나면 디스크에서 프레임을 가져올 때와 선택된 프레임을 디스크로 돌려보낼 때, 두 번이나 디스크에 접근을 해야 합니다. 디스크에 접근하는 것 자체가 굉장히 많은 시간을 필요로 하기 때문에 디스크에 접근하는 횟수를 줄이는 것이 중요합니다.
실행 시간을 최소화 시키기 위해 우리는 페이지 테이블에 변경 비트(Modify Bit, Dirty Bit)라는 비트를 추가하여 사용할 수 있습니다. 이 비트는 페이지가 프로세스에서 사용된 뒤 페이지 내에 만약 어떤 변경된 사항이 있다면 비트를 1로 바꾸어 주는 역할을 합니다. 만일 페이지 교체 시에 이 변경 비트가 0인 페이지를 선택한다면, 아직 페이지가 아무 수정이 되지 않았다는 뜻이기 때문에, 디스크와 동일한 데이터를 갖고 있고, 이 때문에 디스크에 다시 접근하여 수정을 해줄 필요가 없이 프레임을 삭제시켜버리면 됩니다.
디스크에 접근하는 횟수를 줄이는 두 번째 방법은 바로 페이지 교체를 최대한 일어나지 않도록 하는 것입니다. 이것은 페이지 교체 알고리즘을 잘 선택하여 최대한 많이 쓰이는 페이지를 남겨두면 가능할 것입니다. 다음 글에서는 이 페이지 교체 알고리즘들에 대해서 알아보겠습니다.
'전공공부 > 운영체제 (Operating System)' 카테고리의 다른 글
[운영체제] File System Interface (2) | 2021.01.06 |
---|---|
[운영체제] Virtual Memory (2) - Page Replacement Algorithm (1) | 2021.01.04 |
[운영체제] Main Memory (3) - Page Protection, Page Table Structure (0) | 2021.01.04 |
[운영체제] Main Memory (2) - Paging (1) | 2021.01.04 |
[운영체제] Main Memory (1) - Address Binding, Continuous Memory Allocation (0) | 2021.01.03 |