프로그램을 실행하면 메모리에 프로세스가 올라가게 된다.
과거에는 프로세스 전체가 메모리에 올라갔다.
그러나 지금은 프로세스에서 필요로 하는 부분만 올라간다.
이렇게 하게 되면 물리적 메모리 이상으로 프로그램을 실행시킬 수 있다.
이를 가상 메모리(Virtual Memory)라 한다.
그럼 어떻게 운영체제가 가상 메모리를 지원하는지 알아보자.
그 전에 가상 메모리를 이해하기 위해 알아야할 용어들이 있다.
프로세스마다 가지는 주소공간이다.
모든 프로세스는 0번지부터 시작한다.
CPU는 항상 논리주소를 참조한다.
프로세스가 실제 메모리에 올라가는 주소다.
논리적으로는 A 프로세스도 0번지, B 프로세스도 0번지부터 시작하지만,
물리적으로는 다른 주소에 위치하게 된다.
프로세스의 논리 주소를 물리 주소로 변환해 주는 하드웨어다.
프로그램 실행 중에도 주소변환을 빠르게 하기 위함이다.
운영체제는 프로세스를 여러 조각으로 나눠서 관리한다.
이 조각 단위를 page라 한다.
page의 크기는 보통 4KB 정도다.
만약 프로세스가 400MB라면, 100K(약 10만)개의 page조각이 나온다.
page는 메모리에 올라간다.
이러한 page가 들어갈 수 있는 메모리의 공간을 frame이라 한다.
frame은 page와 같은 크기이다.
프로세스의 page가 메모리의 어떤 frame에 있는지를 나타내는 테이블이다.
CPU는 MMU의 도움을 받아 논리 주소를 물리 주소로 변환한다.
page table은 메모리에 위치한다.
cpu는 page를 읽기위해,
page table을 위해 1번, 해당 page가 위치한 frame을 읽기 위해 1번 총 2번 메모리를 읽는다.
valid / invalid bit
page table에서 해당 page가 유효한지를 나타낸다.
reference bit
clock algotithm을 사용하기 위한 bit다.
cpu는 해당 page가 메모리에 존재하면, reference bit를 1로 만든다.
modified bit
메모리에 올라와 있는 page가 수정되었는지 나타낸다.
CPU가 메모리에서 page를 읽으려 할때, 메모리에 page가 없을 수 있다.
이를 page fault라 한다. page fault가 발생하면,
운영체제는 CPU가 필요로 하는 page를 메모리에 가져온다.
이를 swap in이라 한다.
만약 메모리가 꽉 차있다면 그 중 하나를 골라 디스크로 쫓아낸다.
이를 swap out이라 한다.
운영체제가 Page fault에 대처하는 이러한 행동이 가상 메모리를 가능하게 하는 요소다.
구체적인 절차는 다음과 같다.
유효하지 않은 page에 접근하는 경우(=invalid bit) page fault trap이 발생한다.
cpu제어권이 커널로 넘어간다.
만약 해당 프로세스가 주소 밖을 접근하거나, 권한(쓰기 권한이 없는데 쓰는 경우)을 넘어섰다면,
프로세스를 죽인다.
빈 프레임을 가져온다. (없으면 하나를 쫓아낸다.)
해당 페이지를 디스크에서 읽어온다.
a. 디스크 I/O가 끝날 때까지 프로세스는 block상태로 간다.
b. 디스크 I/O가 끝나면 읽어온 페이지를 빈 프레임에 올리고, page table에 frame번호와 valid bit을 기록한다.
c. block상태인 프로세스를 ready queue로 옮긴다.
4번에서 메모리가 꽉 차있는 경우 운영체제는 쫓아낼 프레임을 정하는 기준이 있어야 한다.
이때 사용하는 것이 Clock Algorithm이다.
Clock Algorithm은 LRU의 근사시킨 알고리즘이다.
LRU(Least Recently Used) Algorithm이란?
가장 오래전에 사용된 frame을 내쫓는 알고리즘이다.
예를 들어 frame의 크기가 4개이고,
1, 2, 3, 4번 페이지가 순서대로 왔었다고 하자.
이때 5번 페이지가 들어오기 위해 가장 오래전에 사용된 1번 페이지를 내쫓는 알고리즘이다.
좋은 알고리즘이지만, 이는 운영체제에 적용하기 어렵다.
이유는 cpu의 제어권이 운영체제로 넘어오기 위해서는 page fault가 발생해야 한다.
이 말은 page fault가 발생하지 않으면, 제어권이 넘어오지 않는다는 것이다.
메모리에 해당 page가 있는 경우 cpu는 계속해서 프로세스를 실행한다.
이때 운영체제는 제어권이 없기에, 해당 page에 대한 기록을 할 수 없다.
따라서 page fault가 발생하여 페이지를 교체하려 할 때,
운영체제는 page가 언제 사용되었는지 알지 못한다.
동작과정은 다음과 같다.
메모리를 차례로 읽어간다. 이때 reference bit가 0이라면 쫓아내고, 1이라면 0으로 만든다.
다음 page fault가 발생하면 이전에 쫓아낸 frame부터 읽는다.
메모리의 끝에 도달하면 다시 처음으로 돌아가 읽는다.
위에서 cpu가 메모리에 존재하는 page를 읽는 경우, reference bit을 1로 설정한다고 했다.
reference bit가 1이라는 것은 '이전에 사용된 page' 또는 '아직 1바퀴 돌기 전'이라는 것을 알 수 있다.
이렇게 하면 오래 사용되지 않은 page를 고를 확률이 높아진다.
만약 modified bit가 1이라면, 메모리에서 쫓아내기 전에 디스크에 변경사항을 기록한 후,
swap out해야 한다.