이번엔 <5> 가상 메모리에 대해 공부해보자.
이번 시간엔 운영체제가 메모리를 어떤식으로 관리하는지에 대해 알아보겠다.
📘 먼저 물리 주소와 논리주소에 대해 알아보자.
📌 물리 주소(physical address)
메모리의 하드웨어상 실제주소
📌 논리 주소(logical address)
프로세스마다 부여되는 0번지부터 시작하는 주소체계
현재 메모리 상에 웹 브라우저, 메모장, 게임 프로세스가 적재되어 있다면 이 모든 프로세스에는 0번지부터 시작하는 각자의 논리 주소를 가지고 있는 셈이다.
CPU와 프로세스는 물리 주소가 아니라 논리 주소체계를 이용한다.
중복되는 물리 주소의 번지 수는 존재하지 않지만, 중복되는 논리 주소의 번지 수는 얼마든지 존재할 수 있다.
하지만, 논리 주소라도 실제 정보가 저장되어 있는 하드웨어 상의 메모리와 상호작용하기 위해서는 반드시 논리 주소와 물리 주소간의 변환이 이루어져야 한다.
CPU는 논리 주소로 이야기 하는데, 메모리가 물리 주소로 이야기 한다면 서로 원할하게 통신이 어렵기 마련이다.
그래서 존재하는 하드웨어가 메모리 관리 장치이다.
📌 메모리 관리 장치(MMU, Memory Management Unit)
MMU는 CPU와 메모리 사이에 위치, CPU가 이해하는 논리 주소를 메모리가 이해하는 물리 주소로 변환하는 역할.
📘 연속 메모리 할당은 프로세스들이 메모리 내에서 연속적으로 할당되는 방식을 연속 메모리 할당이라고 부른다.
예를 들어, 프로세스 A는 A의 크기만큼 메모리 주소를 할당 받아서 연속적으로 배치가 되고
B는 B 크기만큼, C는 C 크기만큼 연속적으로 메모리 내에서 배치되는 방식을 메모리 할당이라고 부른다.
이 연속 메모리 할당 방식이 왜 안 좋은지, 어떤 문제를 일으키는지 알아보고 그것을 해결하기 위한 방법인 페이징이라는 방법까지 알아볼 예정인데
그것들을 알아보기 전에,
운영체제가 메모리를 관리하는 아주 기본적인 기능 중에서 스와핑이라는 기능에 대해 먼저 이해할 필요가 있다.
📌 스와핑
현재 사용되지 않는 프로세스들을 보조기억장치의 일부 영역으로 쫓아내고 그렇게 생긴 빈 공간에 새 프로세스를 적재하는 방식.
지금 현재 사용되지 않는 프로세스를 보조기억장치로 쫓아내고 당장 필요한 프로세스를 메모리로 다시 적재할 수 있다면 사용하지 않는 프로세스를 불필요하게 메모리에 적재하고 있을 필요가 없으니, 메모리를 훨씬 효율적으로 관리할 수 있게 된다.
당장 사용되지 않는 프로세스를 보조기억장치의 일부 영역인 스왑 영역(Swap Place)으로 쫓아내는 과정을
스왑 아웃(Swap-out).
스왑 영역에 있었던 프로세스가 다시 메모리로 적재되는 것을
스왑 인(Swap-In).
이렇게 스와핑을 이용하면 프로세스들이 요구하는 메모리 주소 공간의 크기가 실제로 메모리 보다 큰 경우에도 프로세스들을 동시에 실행할 수 있다는 장점이 있다.
예를 들어,
프로세스 A, B, C, D 가 현재 동시에 실행되고 싶은데 프로세스 A, B, C, D 의 크기를 합치면 메모리의 실제 물리 메모리보다 크기가 커진다고 가정을 해보자.
스와핑을 이용하면 이 상황에서도 A, B, C, D 를 동시에 실행할 수 있다.
프로세스 A를 먼저 적재하고, 그 다음 프로세스 B를 적재한다.
그 다음으로는 프로세스 C를 적재한다.
이 때, 프로세스 D를 당장 실행해야 되고 프로세스 B가 실행될 필요가 없다면
프로세스 B를 스왑 아웃 시키고 프로세스 D를 적재하면 된다.
이런 식으로 스왑 인, 스왑 아웃이 반복되면서 실제 물리 메모리보다 큰 프로세스들을 동시에 실행할 수 있게 되는 것이다.
스와핑에 대해 알아봤으니, 이제 진짜 연속 메모리 할당에 대해 알아보자.
프로세스는 실행되기 위해서 메모리 내에 비어있는 공간 적재가 가능한 비어있는 공간에 적재 되어야 한다.
여기서 말하는 빈 공간이라는 것은 적재되어도 괜찮은 공간이라는 뜻이다.
메모리 내 사용자 영역이 이 그림처럼 정의되어 있고, 프로세스 A, B, C 가 현재 실행중이라고 가정을 해보자.
그리고 빈 공간도 A, B, C 세 군데가 있다.
이 상황에서 20MB 크키의 적재할 프로세스가 있고 이 프로세스를 메모리로 적재해야 한다.
당연하게도 적재할 프로세스는 빈 공간에 적재가 되어야 하는데
연속 메모리 할당에서는 어떤 빈 공간에 할당할지에 따라서 크게 세 가지로 나뉜다.
최초 적합, 최적 적합, 최악 적합이 있다.
이 세가지 방식은 연속적으로 프로세스를 메모리 내에 배치할 때 어떤 빈 공간에 어떻게 적재할지에 따라서 나뉘었다고 생각하면 된다.
📌 최초 적합(First-Fit)
운영체제가 메모리 내의 빈 공간을 순서대로 검색하다 적재할 수 있는 공간을 발견하면 그 공간에 프로세스를 배치하는 방식.
검색하는 시간이 최소화되고, 빠른 할당이 가능하다는 장점이 있다.
📌 최적 적합(Best-Fit)
운영체제가 빈 공간을 모두 검색해 본 뒤, 적재 가능한 가장 작은 공간에 할당하는 방식.
📌 최악 적합(Worst-Fit)
운영체제가 빈 공간을 모두 검색해 본 뒤, 적재 가능한 가장 큰 공간에 할당하는 방식.
이 세가지 방법이 연속 메모리 할당 방식이지만, 비효율적이다.
메모리를 효율적으로 사용하는 방법이 아니다.
외부 단편화(External Fragmetation)라는 문제가 발생하기 떄문.
그럼 외부 단편화란 무엇일까.
예를 들어보자.
사용자 영역이 200MB 정도 있다.
크기가 50MB인 프로세스 A, 30MB인 프로세스 B, 100 MB인 프로세스 C, 20MB인 프로세스 D를 차례대로 적재해야 한다면?
운 좋게 이렇게 딱 맞게 적재가 됐다고 하자.
근데 여기서 프로세스 B 와 D의 실행이 끝났다.
빈 공간은 총 50MB가 남지만, 50MB 짜리 프로세스를 적재할 수는 없다.
이러한 문제를 외부 단편화라 한다.
📘 외부 단편화란, 프로세스들이 실행되고 종료되길 반복하며 메모리 사이 사이에 빈 공간이 발생하고, 그 공간들이 프로세스를 할당하기 어려울 만큼 작은 공간들이라 메모리가 낭비되는 현상이다.
연속 메모리 할당 방식은 언뜻 들으면 합리적이라고 생각될 수 있지만, 외부 단편화라는 부작용도 존재하는 방식이다.
외부 단편화를 해결하는 방법이 있다.
그 중 대표적인 방법 중 하나가 메모리 압축(compaction)이다.
📌 메모리 압축(compaction)은 메모리 조각 모음이라고도 부른다.
여기저기 흩어져 있는 빈 공간들을 하나로 모으는 방식이다.
프로세스를 적당히 재배치시켜 흩어져 있는 작은 빈 공간들을 하나의 큰 빈 공간으로 만드는 방법이다.
물론 이 방법도 부작용이 있긴 하다.
여기저기 흩어져 있는 빈 공간을 하나로 합치는 과정에서, 그리고 현재 실행 중인 프로세스를 재배치 하는 과정에서 당연하게도
많은 오버헤드를 야기할 뿐만 아니라 프로세스들은 자신들이 해야 할 일을 못하기 때문이다.
그래서 이 방법보다는 대중적으로 사용하는 페이징이라는 기법에 대해 알아보도록 하겠다.
📌 페이징(paging)
페이징은 가상 메모리 관리 기법 중 하나로, 모든 프로세스를 일정한 크기로 자르고 메모리에 불연속적으로 할당해 외부 단편화를 해결하는 방법이다.
좀 더 정리해 보자면,
페이징은 프로세스의 논리 주소 공간을 페이지(page)라는 일정 단위로 자르고, 메모리의 물리 주소 공간을 프레임(frame)이라는 페이지와 동일한, 일정한 단위로 자른 뒤 페이지를 프레임에 할당하는 가상 메모리 관리 기법이다.
물리 주소에 적재되는 대상들이 연속 메모리 할당 방식에 비하면 조금 더 균일한 크기를 갖고 있기 때문에 외부 단편화가 거의 발생하지 않게 된다.
참고로, 페이징에서도 스와핑을 사용할 수 있다.
프로세스 단위의 스왑 인, 스왑 아웃이 아니라 프레임 단위의 페이지를 내보내고 적재하는 방식으로 스와핑을 할 수 있다.
페이징에서 스왑 인은 페이지 인, 스왑 아웃은 페이지 아웃이라고 한다.
페이지 인, 페이지 아웃 이라고 하는 기술을 본다면
어떤 프로세스를 실행하기 위해서 모든 페이지가 전부 다 메모리에 저장 되어 있을 필요는 없다는 점을 보여주니 알아두자.
근데 여기서 문제가 있다.
페이징은 프로세스들이 메모리 내에서 불연속적으로 위치해 있을 수도 있다고 했다.
그렇기에, CPU 입장에서는 프로세스가 현재 어디에 저장되어 있는지 알기가 쉽지 않다.
그 말은 다음에 실행할 명령어가 어디에 있는지 찾기 어렵다는 말이다.
이런 문제를 해결하기 위해서 사용되는 개념이
📌 페이지 테이블 이다.
어떤 프로세스에, 어떤 페이지가, 어떤 프레임에 할당되어 있는지를 짝지어 주는 일종의 이정표.
(실제 메모리 내의 주소인) 물리 주소에 불연속적으로 배치되더라도,
(CPU가 바라보는 주소인) 논리 주소에는 연속적으로 배치하는 방법
페이지 테이블에는
어떤 프로세스에 어떤 페이지가 어떤 프레임에 할당 되어 있는지가 적혀있다.
이 페이지 테이블을 통해서 현재 프로세스가 물리 주소내에서는 실제로 불연속적으로 배치되어 있다 하더라도 CPU 입장에서는 마치 연속적으로 배치되어 있는 것처럼 보이도록 한다.
페이지 테이블은 프로세스마다 있다.
프로세스마다 페이지가 있고 그 페이지는 각기 다른 프레임에 할당될 수가 있기 때문이다.
페이징은 외부 단편화 문제를 해결할 수 있지만
내부 단편화라는 문제를 만들어내기도 한다.
페이징은 프로세스의 논리 주소 공간을 페이지라는 일정한 크기의 단위로 나누는 방식이지만, 모든 프로세스가 페이지의 크기에 맞게 나뉘는 것은 아니다.
가령 페이지의 크기는 10KB 인데
프로세스의 크기가 107KB인 경우 마지막 페이지는 3KB만큼 남게 된다.
이렇게 페이지 하나의 크기보다 작은 크기로 발생하게 되는 메모리 낭비를 내부 단편화(Internal Framentation)이라고 한다.
프로세스마다 페이지 테이블이 있고, 각 페이지 테이블은 CPU 내의 프로세스 테이블 베이스 레지스터(PTBR)가 가리킨다.
CPU가 프로세스 A를 실행하고 있다면
프로세스 A를 이루고 있는 페이지들이 현재 어떤 프레임에 적재되어 있는지를 알아야 한다. 그걸 알기 위해서는 페이지 테이블을 참조해 봐야 한다.
그리고 그 페이지 테이블이 현재 어디에 저장되어 있는지를 알아야 한다.
그 위치를 PTBR, 프로세스 테이블 베이스 레지스터가 가리키고 있다고 보면 된다.
여기서 문제가 있다.
이렇게 페이지 테이블이 메모리에 저장되어 있으면 어떤 문제가 있을까?
페이지 테이블이 메모리에 있으면 부작용이 생기는데,
그 부작용은 메모리에 접근 시간이 두 배로 늘어날 수 있다는 거다.
페이지 테이블을 참조하기 위해 한 번, 프레임, 즉 페이지에 참조하기 위해 또 한 번 이렇게 두 번씩 접근하기 때문이다.
이 문제를 위해 TLB라고 하는 특별한 캐시 메모리를 이용한다.
📌 TLB
페이지 테이블의 일부를 가져와 저장하는 캐시 메모리.
방금 전 말했던 방법처럼 메모리에 두번씩 접근하는게 아니라,
현재 자주 참고하고 있는 페이지 테이블이 있다면 TLB를 통해서 페이지와 프레임을 곧바로 확인하고 메모리에 접근하게 된다.
불필요한 메모리 접근을 줄일 수 있게 해준다.
캐시 미스, 캐시 히트처럼 TLB도 마찬가지이다.
TLB 미스는 메모리 접근을 두 번 해야 되는 것을 알 수 있다.
페이지 테이블에 대해 좀 더 자세히 알아보자.
페이지 테이블에 각각의 행들이 있다.
이 행들을 페이지 테이블의 페이지 테이블 엔트리(PTE)라고도 부른다.
지금까지 설명했던 페이지 테이블 엔트리는 두 가지였다.
페이지 번호와 프레임 번호.
이 거 두개 외에도 다양한 정보가 담기는데, 운영체제마다 다르지만
대중적인 정보들에 대해 알아보겠다.
먼저, 유효비트(Valid Bit).
유효비트도 페이지 테이블에 포함되어 있는 경우가 많은데,
현재 해당 페이지에 접근 가능한지 여부를 알려주는 비트이다.
현재 페이지가 스왑 영역으로 쫓겨났는지, 메모리에 적재되어 있는지 아닌지를 나타낸다고 보면 된다.
유효비트가 1이라면 현재 메모리에 적재 되어 있다고 볼 수 있고, 0이라면 이 페이지는 메모리에 없고 보조기억장치, 그러니까 스왑 영역에 있다는 뜻이다.
유효 비트가 0인 페이지에 접근하려고 하면
페이지 폴트(page fault)라는 인터럽트가 발생을 한다.
페이지 폴트 인터럽트는 현재 접근하려고 하는 페이지가 메모리에 적재 되어 있지 않을 경우에 발생하는 인터럽트다.
이 또한 같은 인터럽트기 때문에 다른 인터럽트를 처리하는 방식과 같다.
다음은 보호 비트다.
보호 비트는 페이지 보호를 위해 존재하는 비트다.
어떤 페이지는 읽기만 해야 되는 페이지일 수도 있고, 어떤 페이지는 읽기와 쓰기가 모두 가능한 페이지일 수도 있다.
읽기 전용 페이지에 어떤 새로운 정보를 저장하면 안 되기 때문에 쓰기 권한이 없다면 보호 비트를 0으로 설정할 수 있다.
읽기만 가능한 페이지는 100, 쓰기만 가능한 페이지는 111 등 이런식으로 실행 권한을 나눠서 설정하는 경우도 있다.
그리고 다음은 참조 비트.
참조 비트는 CPU가 이 페이지에 한 번이라도 접근한 적이 있는지 여부를 나타내는 비트다.
어떤 페이지가 메모리로 적재된 후에 CPU가 한 번이라도 읽거나 쓴 페이지는 참조 비트가 1로 세팅이 되고, 페이지가 적재된 이후 한 번도 CPU가 방문한 적이 없다면 비트는 0이 된다.
그리고 수정비트.
더티 비트(Dirty Bit)라고도 부른다.
CPU가 이 페이지에 한 번이라도 데이터를 쓴 적이 있는지 여부를 알려준다.
이 페이지가 현재 수정이 됐는지 아닌지 여부를 알려주는 것.
이 비트가 1이라면 한 번이라도 변경된 적 있는 페이지를 의미하고, 만약에 0이라면 변경된 적이 없는 페이지를 나타낸다.
스와핑 수정 비트는 존재하는 이유가 뭘까?
페이지가 메모리에서 사라질 때 보조기억장치의 쓰기 작업을 해야 되는지 할 필요가 없는지 판단하기 위해 존재한다.
예를 들어
메모리에 어떤 페이지 A라고 하는 페이지가 있고 CPU가 만약에 이 페이지를 읽기만 했다.
만약에 한 번도 이 페이지에 새로운 정보를 쓴 적이 없다라고 한다면 페이지A는 메모리에 있는 내용과 보조기억장치에 있는 내용이 같을 수 밖에 없다. 변경한 적이 없으니까.
만약 CPU가 이 페이지의 내용을 변경했다면 이 페이지는 스왑 아웃 될 때 변경된 내용을 보조기억장치에도 반영을 해야 한다.
그것을 수정비트를 통해 판단하는 것.
자, 이제 페이지 교체 알고리즘과 프레임 할당 기법에 대해 알아보자.
페이징을 통해 물리 메모리보다 큰 프로세스를 실행할 수 있다고 배웠다.
하지만 그럼에도 물리 메모리의 크기는 명확하게 한정되어 있다.
운영체제 입장에서는 두 가지의 문제를 해결해야 한다.
첫번째로는,
기존에 적재된, 메모리에 불필요한 페이지를 선별해서 보조기억장치로 내쫓아야 하고
두번째로는,
프로세스들한테 적절한 수의 프레임을 할당할 수 있어야 한다.
이 첫 번째 문제를 해결할 수 있는 것이 페리지 교체 알고리즘이다.
두 번째 문제를 해결할 수 있는 것은 프레임 할당 기법이다.
이것들을 배워 보기 전 먼저 알아야 할 용어가 있다.
요구 페이징(demand paging)이다.
요구 페이징은 메모리에 필요한, 요구되는 페이지만을 적재하는 기법을 요구 페이징이라고 한다.
요구 페이징의 기본적인 양상은 이렇다.
참고로, 아무런 페이지도 메모리에 적재하지 않은 패 무작정 프로세스를 실행할 수도 있는데 이것을 순수 요구 페이징(pure demand paging)이라고 한다.
다시 요구 페이징으로 돌아가보자.
이 페이징 기법으로 페이지들을 적재하다 보면 언젠가는 메모리가 꽉 차게 된다.
그럴 때 당장 실행해야 하는 페이지가 있다면 지금 당장 사용되지 않고 적재되어 있는 페이지는 보조기억장치로 보내야 한다.
이 때 어떤 페이지를 내보내야 할까?
그것을 결정하는 것이 페이지 교체 알고리즘이다.
페이지 교체 알고리즘 중 무엇이 좋은 페이지 교체 알고리즘일까.
일반적으로 페이지 폴트를 가장 적게 발생시키는 것이 좋은 페이지 교체 알고리즘이다.
페이지 폴트가 발생하면 보조기억장치로부터 필요한 페이지를 다시 갖고 와야 해서 메모리에 적재한 페이지를 갖고 오는 것보다 느려지기 때문이다.
그렇기에 페이지 폴트가 발생한 횟수를 알 수 있어야 한다.
횟수를 알기 위해서 사용하는 개념이
페이지 참조열(page reference string)이다.
페이지 참조열은 CPU가 참조하는 페이지들 중에서 연속된 페이지를 생략한 페이지열을 페이지 참조열이라고 한다.
이제 진짜 페이지 교체 알고리즘에 대해 알아보자.
첫 번째로 알아볼 페이지 교체 알고리즘은
📘 FIFO 페이지 교체 알고리즘(First-In First_Out Page Replacement Algorithm)
이름 그대로 메모리에 가장 먼저 적재된 페이지부터 스왑 아웃하는 페이지 교체 알고리즘이다.
이 알고리즘은 구현 자체는 간단하지만, 마냥 좋은 건 아니다.
초기에 적재되어 프로그램 실행 내내 사용될 페이지가 있을 수도 있는데
먼저 적재됐다고 내쫓으면 안되기 때문이다.
FIFO 페이지 교체 알고리즘의 문제를 보완한 변영 버전이 있는데
📘 2차 기회(second-chance) 페이지 교체 알고리즘이다.
2차 기회 알고리즘 또한 기본적으로 메모리에 오래 적재되어 있던 페이지를 먼저 쫓아낸다.
여기서 다른 점은 참조 비트가 1일 경우에, 이것은 CPU가 한 번 참조한 적이 있다는 것이기 때문에 바로 내쫓지 않고 적재된 시간을 현재 시간으로 설정하고 다시 맨 끝으로 보낸다.
가장 최근에 적재된 페이지로 간주하는 것.
그리고 가장 오래 머물렀던 페이지의 참조 비트가 0이라면 가장 오래 머물렀음에도 CPU가 한 번도 참조하지 않은 것이기 때문에 페이지를 내보낸다.
CPU가 참조하는 횟수를 고려하는 페이지 교체 알고리즘이다.
최적의 알고리즘이지만, 앞으로 가장 적게 사용할 페이지를 미리 예측하기가 어렵기 때문에 실제 구현이 어려운 알고리즘이다.
그 다음 알아볼 알고리즘은
📘 LRU 페이지 교체 알고리즘(Least Recently Used Page Replacement Algorithm)
최적 페이지 교체 알고리즘이 가장 적게 사용할 페이지를 스왑 아웃한다면
LRU 페이지 교체 알고리즘은 가장 적게 사용한 페이지를 교체하는 알고리즘이다.
보편적으로 사용되는 페이지 교체 알고리즘의 원형이고, 이를 기반으로 만들어진 다양한 파생 알고리즘들이 있다.
나중에 기회가 된다면 좀 더 알아보도록 하자.
이제 프레임 할당에 대해 알아보자.
페이지 폴트가 자주 발생하는 이유에는 나쁜 페이지 교체 알고리즘만 있는 것은 아니다.
하나의 프로세스가 사용할 수 있는 프레임 수 자체가 적어도 페이지 폴트는 발생하기 때문이다.
프로세스가 사용할 수 있는 프레임 수가 많으면 페이지 폴트의 빈도가 확연히 줄어든다.
CPU가 쉴 세 없이 프로세스를 실행해야 컴퓨터의 전체적인 생산성도 당연히 올라갈텐데 페이지 교체에 너무 많은 시간을 쏟으면 당연하게도 악영향이 갈 수 밖에 없다.
이렇게 실제로 프로세스가 실행되는 시간보다 페이지 교체에 더 많은 시간을 소요해서 성능이 전체적으로 저하되는 문제를
스래싱(Thrasing)이라고 한다.
스래싱이 발생하는 근본적인 문제가 방금전에도 말했듯
각각의 프로세스가 필요로 하는 최소한의 프레임 수가 보장이 되어 있지 않기 때문이다.
가장 단순한 형태의 프레임 할당 방식부터 알아보자면
균등 할당 방식이 있다.
이 방식은 모든 프로세스들한테 균등하게 프레임을 할당하는 방식이다.
300개의 프레임을 할당할 수 있는 시스템이 있고 3개의 프로세스가 동시에 실행 중이라면 각 프로세스당 100개의 프레임을 할당해주는 방식이다.
프로세스들의 크기가 모두 다른데 동일한 프레임의 수를 할당하는 것은 비효율적이기도 하다.
그래서 다음 알아볼 프레임 할당 방식이
비례 할당 방식이다.
비례 할당 방식은 프로세스들의 크기를 고려해 프로세스의 크기가 크면 프레임을 많이 할당하고 프로세스의 크기가 작으면 프레임을 작게 할당한다.
균등 할당과 비례 할당은 프로세스의 실행 과정은 고려하지 않고 프로세스의 크기나 물리 메모리의 크기만 고려한 방식이기 때문에
정적 할당 방식이기도 하다.
비례 할당 방식도 완벽한 방식은 아니다.
프로세스의 크기가 물리적으로 클 지라도 막상 실행을 해보니 많은 프레임이 필요하지 않은 경우도 있고, 반대의 경우도 있기 때문이다.
그래서 프로세스를 실행하는 과정에서 프레임을 결정하는 방식이 필요하게 된다.
작업집합 모델을 활용하는 방식과 페이지 폴트 빈도를 이용하는 방식이 있다.
작업집합 모델은
Working Set 모델이라고도 부르는데, CPU가 특정 시간동안 참조한 페이지 개수만큼 프레임을 할당해 주는 방식이다.
그리고 다음은
페이지 폴트 빈도를 이용하는 방식이다.
페이지 폴트 빈도 기반 할당 방식은
페이지 폴트율이 너무 높으면 그 프로세스는 너무 적은 프레임을 갖고 있다.
페이지 폴트율이 너무 낮으면 그 프로세스는 너무 많은 프레임을 갖고 있다.
이 두 가지 가정에서 생겨난 아이디어가 페이지 폴트 빈도 기반 할당 방식이다.
다시 말해서 페이지 폴트율의 상한선과 하한선을 정하고 이 범위 안에서만 프레임을 할당하는 방식이다.
방금 설명한 이 두가지 방식들은 프로세스가 실행되는 과정을 관찰해 프레임을 할당하는 방식이기에 동적 할당 방식이라고도 한다.
이번 챕터는 여기까지 알아보도록 하겠다.