hongcheol / CS-study

cs지식을 정리하는 공간
MIT License
242 stars 30 forks source link

OS 가상 메모리 정리입니다~! #53

Open capo-YoonJu opened 3 years ago

capo-YoonJu commented 3 years ago

가상 메모리(Virtual Momory)

현재 실행중인 코드는 반드시 물리 메모리에 존재해야한다고 생각할 수 있습니다. 하지만 다음과 같은 상황을 생각해봅시다.

  • 프로그램에서 가끔 발생하는 예외를 처리하기 위한 코드
  • 크기가 제한된 형태인 배열(array)을 이용하기 위해 필요한 크기보다 훨씬 큰 크기로 선언한 경우
  • 정말 가끔 사용하는 옵션
  • 위와 같이 당장 필요하지 않은 코드들

위와 같은 경우를 고려했을 때 모든 코드를 늘 물리 메모리에 올려놓을 필요는 없으며, 그렇게 한다고 할지라도 물리 메모리 크기는 제한적이기 때문에 불가능할 수도 있습니다.

이를 해결하기 위해 가상 메모리를 사용합니다. 가상 메모리는 실제의 물리 메모리 개념과 사용자의 논리 메모리 개념을 분리한 것입니다. 프로그램 중 당장 필요한 일부만을 물리 메모리에 올려놓고 실행하는 것이죠.

이점

Virtual-Memory


요구 페이징

일반적인 가상 메모리는 보통 요구 페이징으로 구현합니다. 요구 페이징은 프로그램 실행 시 모든 부분을 메모리에 적재하는 것이 아니라, 실행 과정에서 페이지를 요구할 때마다, 즉 페이지들이 필요해질 때마다 적재하는 전략입니다.

요구 페이징은 스와핑과 개념이 유사합니다. 스와핑에서는 보조 메모리의 프로세스를 실행하고 싶을 때에 주 메모리로 읽어옵니다(swap in). 이와 같이 프로세스 내 페이지를 관리하는 페이저(pager)는 프로세스가 스왑 아웃(swap out)되기 전에 실제로 사용될 페이지가 어떤 것일지 추측하고, 이후에는 프로세스 전체를 스왑인 하는 대신 실제 필요한 페이지만 메모리로 읽어옵니다.

이를 위해서는 하드웨어 적인 기술이 필요한데, 유효/무효 비트를 사용하여 페이지가 메모리에 존재할 경우 유효(valid)하다고 표시하고, 페이지가 가상 주소 공간에 정의되지 않았거나 디스크에 존재할 경우 무효(invalid)하다고 표시하거나 페이지가 현재 저장된 디스크 주소를 기록합니다.

순수 요구 페이징

특정 페이지가 필요해 실제로 참조하기 전에는 절대 그 페이지를 메모리로 적재하지 않는 방법을 말합니다. 이를 통해 전체 프로세스가 주 메모리에 올라와있지 않아도 프로세스를 실행할 수 있습니다.

메커니즘은 다음과 같습니다.

  1. 실제로 참조하지 않는 페이지는 초기에 메모리에 올리지 않으므로 어떤 페이지도 메모리에 올라가 있지 않음
  2. 특정 페이지에 대한 참조가 발생
  3. 페이지 부재(page fault) 발생
  4. 운영체제는 내부 테이블을 통해 해당 페이지가 디스크 내부 어디에 위치했는지 파악
  5. 자유 프레임을 탐색하여 디스크로부터 해당 페이지를 읽어옴
  6. 페이지 테이블 내애 페이지에 변화가 생겼음을 표시
  7. 3에서 페이지 부재로 중지되었던 명령이 다시 실행됨

위에서 볼 수 있듯이 요구 페이징의 성능은 페이지 부재에 의해 좌우됩니다. 따라서 페이지 부재율을 낮게 유지하는 것이 중요하겠죠.


페이지 교체

요구 페이징에서 주요 관건은 페이지 교체와 프레임 할당 문제를 해결하는 것입니다. 디스크 입/출력 비용은 결코 만만하게 볼 수 없기때문이죠.

먼저 페이지 교체부터 봅시다. 실제 시스템이 보유한 페이지보다 더 많은 프로세스가 더 많은 페이지를 요구할 경우, 페이지 간 교체를 해야하는 문제가 발생합니다. 이렇게 희생될 페이지를 골라야 하는 순간에서 고려할 수 있는 페이지 교체 알고리즘에 대해 알아봅시다.


FIFO 페이지 교체(First-In-First-Out)

FIFO-page-replacement


최적 페이지 교체(OPT, Optimal page replacement)

OPT-page-replacement


LRU 페이지 교체(Least-Recently-Used)

LRU-page-replacement


LRU 근사 페이지 교체(LRU Approximation)

하드웨어의 지원을 필요로하는 LRU 페이지 교체 알고리즘의 한계를 극복하기 위한 알고리즘입니다. 주로 페이지 별 참조 비트를 설정하여 사용합니다.

부가적 참조 비트 알고리즘

이차 기회 알고리즘(클럭 알고리즘)


계수 기반 페이지 교체(Counting-Based)

LFU 알고리즘(Least-Frequently-Used)

MFU 알고리즘(Most-Frequently-Used)


프레임 할당

요구 페이징의 두번째 관건은 프레임 할당입니다. 여러 프로세스에게 각각 얼마나 많은 프레임을 할당해야할지 결정하는 문제이죠. 프레임 할당에 따라 페이지 부재율이 달라질 수 있기때문에 프레임 할당은 페이지 교체와 더불어 중요하게 작용합니다. 다양한 프레임 할당 알고리즘에 대해 소개합니다.

균등 할당


비례 할당


전역 대 지역 할당

이제서야 밝히지만 프레임 할당에는 또 다른 중요한 요인이 있습니다. 바로 페이지 교체를 고려하는 것인데, 구체적으로 전역 교체지역 교체 라는 두 가지 범주로 나눌 수 있다는 것입니다.


쓰레싱(Thrashing)

만약 한 프로세스가 프레임을 부족하게 할당받는다면 페이지 집합도 부족하게 할당받게 될 것이고, 이는 페이지 부재를 발생시킬 것입니다. 하지만 만약 다른 프로세스들도 모두 열심히 일하고 있는 상황이라 페이지를 내어줄 수 없다면 어떻게 될까요? 다른 프로세스로부터 억지로 페이지를 뺏어오더라도 바로 다시 해당 프로세스가 페이지 부재를 발생시켜 결국 페이지를 되돌려줘야하는 문제가 발생할 수 있습니다.

이와 같은 치열한 눈치싸움, 과도한 페이징 작업을 쓰레싱이라 합니다. 쓰레싱은 어떤 프로세스가 실제 실행보다 더 많은 시간을 페이징에 사용하고 있는 것을 말합니다. 쓰레싱이 발생하면 성능은 심각하게 저하됩니다.

쓰레싱은 전역 페이지 교체 알고리즘을 이용하여 다중 프로그래밍 정도를 높일 때 발생할 수 있습니다. 운영체제는 다중 프로그래밍 정도를 높이기 위해 CPU 이용률이 낮아지면 새로운 프로세스를 추가합니다. 이때 다른 프로세스의 프레임을 할당받는 전역 페이지 교체 알고리즘을 적용한다면 다른 프로세스도 프레임이 부족한 상황에서는 서로의 프레임을 자꾸 할당받으려 할 것입니다. 이 과정에서 CPU는 다시 놀게되고, 운영체제는 더 많은 프로세스를 추가시켜버리는 것이죠. 이러한 악순환이 반복되어 쓰레싱이 발생합니다.

쓰레싱은 지역 교환 알고리즘 혹은 우선순위 교환 알고리즘을 적용하여 막을 수 있지만, 좀 더 근본적인 해결책은 각 프로세스가 필요로 하는 최소한의 프레임 수를 보장하는 것입니다. 이를 위해서는 작업 집합 모델에 대해 이해해야 합니다.


작업 집합 모델(Working-Set Model)

작업 집합 모델은 프로세스가 필요로 하는 최소한의 프레임 수를 알 수 있는 방법으로, 쓰레싱을 조절하는 방법 중 하나입니다. 작업 집합 모델은 지역성 개념을 기반으로 합니다.

지역성 모델이란 프로세스가 실행될 때는 항상 어떤 특정 지역에서만 메모리를 집중적으로 참조한다는 개념입니다. 이에 따라 지역성은 집중적으로 함께 참조되는 페이지들의 집합을 의미합니다.

지역성을 고려하여 작업 집합을 구성하는 방법은 다음과 같습니다. 특정 프로세스가 최근 참조한 페이지들 중 Δ개의 페이지를 작업 집합으로 구성합니다. 이후 한 페이지가 더이상 사용되지 않는다면 해당 페이지의 마지막 참조로부터 Δ만큼의 새로운 페이지가 작업 집합으로 구성될 것이고, 사용되지 않는 페이지는 집합에서 제외됩니다.

작업 집합의 정확도에서 중요한 것은 Δ값, 즉 집합의 크기겠죠. Δ값이 너무 커지면 지역성을 과도하게 수용할 것이고, Δ값이 너무 작아지면 지역을 포함하지 못할 것입니다.

작업 집합을 설정하게 된다면 운영체제는 각 프로세스의 작업 집합을 통해 프로세스에게 맞는 크기의 프레임을 할당할 수 있습니다. 따라서 가능한 최대의 다중 프로그래밍 정도를 유지하면서도 쓰레싱을 방지할 수 있게됩니다.

하지만 작업 집합을 추적하는 것이 쉬운 일은 아닙니다. 여기서도 참조 비트를 활용하여 구현해야 합니다. 타이머 인터럽트를 발생시켜 현재 작업 집합의 참조 비트와 이전 단위의 작업 집합의 참조 비트를 비교하는 방식으로 구현할 수 있지만, 이런 방식은 정확도가 낮고 오버헤드가 크다는 문제가 있습니다.


페이지 부재 빈도(PFF, Page-Fault Frequency)

쓰레싱을 조절하는 또 다른 방법은 페이지 부재 빈도 모델입니다.

쓰레싱의 개념에 대해 다시 생각해봅시다. 쓰레싱이 발생했다는 것은 페이지 부재율이 높다는 것을 의미합니다. 페이지 부재율이 높으면 더 많은 프레임이 할당되어야하고, 페이지 부재율이 낮으면 너무 많은 프레임을 할당해 낭비가 될 수 있습니다.

따라서 페이지 부재율을 조절해야할텐데, 단순하게 페이지 부재율의 상한과 하한을 설정한다고 생각해봅시다. 페이지 부재율이 상한을 넘어가게 되면 해당 프로세스에게 더 많은 프레임을 할당해주면 됩니다. 또한 하한보다 낮아지게 된다면 해당 프로세스로부터 프레임을 빼앗아 다른 프로세스에게 할당해주면 됩니다.

페이지 부재 빈도 모델을 통해 직접적으로 페이지 부재율을 관리할 수 있고 쓰레싱도 막을 수 있습니다.

capo-YoonJu commented 3 years ago

사진 등록은 실패했습니다..