CPU가 특정 페이지에 접근하는 명령어를 실행 했을 때, 해당 페이지가 스왑영역(유효비트가 0)에 있어서 당장 실행시킬 수 없는 상태일 경우에는 '페이지 폴트'예외가 발생.
페이지 폴트 예외 발생시 스왑인 작업으로 유효비트를 0에서 1로 스와핑 잡업이 먼저 진행된 후 프로세스를 실행할 수 있는 상태를 만들어 준후 프로세스가 실행된다.
실행할 모든 프로세스를 메모리에 올려두는 것은 시스템에 부담이 될 수 있는 만큼 당장 필요한 페이지만을 메모리에 우선 적재하는 방법을 가리켜 '요구 페이징'이라 한다.
위와 같이 스왑인을 실행하기 위해 메인메모리에 빈공간을 만들어 주기 위해 메인메모리에 들어찬 페이지 중 어떤 페이지를 스왑 영역으로 보낼 것인지 결정하고 그것을 처리하는 것을 페이지 교체라고 한다. 페이지 교체 정책에는 세가지 대표적인 방식이 있다.

<출처: 유노코딩>
페이지 폴트 발생 시 가장 먼저 들어간 페이지1이 빠지고 그 자리에 페이지4가 들어가게 된다.
그리고 페이지1이 다시 들어가고 싶다면 그다음 들어간 페이지3이 빠지고 그 자리에 페이지1이 들어간다.
CPU에 의해 참조되는 횟수를 고려해서 자주 사용될 예정인 페이지를 내버려 두고,
사용이 거의 되지 않을 예정인 페이지를 교체하는 방식이다.
어떤 프로세스가 얼마나 빈번히 사용될지 알 수 없어 이론적으로만 존재하는 방식이다.

최근 사용 빈도가 가장 적은 페이지를 선택하는 방법임. 최근에 오랫동안 사용되지 않은 페이지가 사용되지 않을 확률이 높다 생각해 스왑 영역으로 보내는 방법.
이 모든 것의 근본적인 이유는 메모리 공간의 부족, 즉 프레임 부족이다.
프레임이 부족하면 페이지 폴트가 자주 발생한다. 페이지 폴트가 발생하면 잦은 스와핑 작업으로 인해 CPU사용률이 떨어지게 된다.
CPU사용률이 떨어지면 운영체제는 더 많은 프로세스를 메모리에 올리려 하고, 이는 더 잦은 페이지 폴트로 이어져 악순환에 빠지게 되는데 이러한 문제를 '스레싱'이라고 한다.
이를 해결하는 가장 쉬운 방법은 메인메모리를 크게 해주면 되는데 쉬운 방법이 아니다.
<선입선출 예제>
# 선입선출 모델 구현
class PageReplacementFIFO :
def __init__(self, capacity):
self.capacity = capacity
self.pages = []
def access_page(self, page) :
if page not in self.pages :
if len(self.pages) >= self.capacity :
self.pages.pop(0) # 제일 앞에 있는 친구를 뺸다.
self.pages.append(page)
def status(self):
print("현재 페이지 상태:", self.pages)
page_replacement = PageReplacementFIFO(capacity=3)
page_replacement.status()
page_replacement.access_page(3)
page_replacement.status()
page_replacement.access_page(2)
page_replacement.status()
page_replacement.access_page(1)
page_replacement.status()
page_replacement.access_page(4)
page_replacement.status()
<실행결과>

가장 먼저 들어간 3이 빠지고 4가 들어가는 것을 볼 수 있음.