가상 메모리가 무엇일까? 물리적 주소와 논리적 주소를 이해했다면 쉽게 이해할 수 있다. 왜냐하면 메모리는 주소의 집합이기 때문이다. 가상 메모리는 가상 주소의 집합에 불과하다. 우리는 논리적 주소(가상 주소)를 'CPU 입장에서의 주소'라했고, 모든 프로세스의 가상 주소는 0부터 시작한다고 했다(여기 참고). 이렇게 모든 프로세스는 각각 독립적인 가상 주소 공간을 가지는데, 이를 가상 메모리라고 한다. 그렇다면 가상 메모리를 사용하는 이유는 무엇일까? 크게 아래 세 가지를 뽑을 수 있다.
1. 사용자 편의성
사용자는 가상 메모리만 신경쓰면 된다. 물리적 메모리로의 사상은 OS가 알아서 한다.
2. 프로세스간 메모리 보호
Base Register와 Limit Register로 프로세스는 물리적 메모리에서 자신의 접근 영역을 알 수 있다. 접근 영역을 벗어나면 trap 발생.
3. 프로세스가 물리적 메모리의 크기에 한정되지 않는다.
물리적 메모리보다 더 큰 크기의 프로그램을 실행시킬 수 있다는 말이다. 이거는 아래에서 설명..
3번이 이번 글의 주제다. 참고로 3번을 제외한 지금까지의 모든 내용은 이미 다룬 내용이기 때문에 만약 이해가 안 된다면 '메모리 파트'를 읽고 오는 것을 추천한다. 이번 글의 학습 목표는 아래의 질문에 답하는 것이다.
어떤 프로그램을 실행시키려고 하는데 물리적 메모리에 여유 공간이 없다면?
Swapping
프로그램을 실행시키려면 데이터가 메모리 위에 올라가야 한다. 이는 불변의 법칙이다. 오직 메모리 위에 있는 내용만 컴퓨터가 실행할 수 있다. 아래 그림을 보자. 어떻게 문제를 해결할 수 있을까?
프로세스 P2가 실행되기 위해서는 메인 메모리에 로딩돼야 하는데 물리적 메모리에 여유 공간이 없는 상황이다. 여기서 프로세스 P2를 실행시키기 위해서는? 좀 무식하기는 하지만 P1을 그대로 보조기억장치(SSD)에 옮겨 자리를 만들어주고, 빈자리에 P2를 넣는 방법이 있다. 이를 Swapping이라고 한다. 메인 메모리에서 SSD로 가는 것을 'swap out', SSD에서 메인 메모리로 가는 것을 'swap in'이라고 한다.
Swapping
: 두 개의 프로세스를 통째로 바꿔치기 하는 개념
ex) 위 그림에서 process P1는 메모리 → 보조기억장치 이동, process P2는 보조기억장치 → 메모리 이동
그런데 뭔가 딱봐도 굉장히 비효율적이다. 안그래도 SSD까지 멀어 죽겠는데, 프로세스의 모든 내용을 옮기다니!! 오버헤드가 굉~장히 심할게 뻔하다. 따라서 현대의 OS는 이 방법을 쓰지 않고, Demand Paging이라는 방법을 쓴다.
Demand Paging
우선 한가지 짚고 넘어가야할 부분이 있다. 과연 프로그램을 실행할 때 SSD에 저장되어 있는 모든 내용을 다 메모리에 옮길 필요가 있을까? 없다. 왜냐하면 우리가 프로그램을 실행할때 사용하는 기능은 극히 일부이기 때문이다. 한가지 예를 들어보자.
GTA 게임은 용량이 자그마치 80GB 정도 된다. 게임을 다운받고 실행시켰다고 가정해보자. GTA에는 수많은 맵이 있고, 스토리 설정을 위한 애니메이션도 많고, 캐릭터도 다양하고, 아이템도 많다. 그런데 우리가 화면상에서 플레이하는 맵은 수많은 맵중에 하나 뿐이다. 즉, 현재 플레이하고 있는 맵의 정보만 메모리 위에 있으면 게임하는데 아무 지장이 없다. 맵 이동을 하면? SSD에서 바뀐 맵의 데이터를 로딩해주면 된다. 게임을 플레이할 때 맵이 바뀌면 로딩 시간이 있는 이유가 이 때문이다.
내가 하고 싶은 말은 프로그램 실행에 필요한 코드는 아주 일부분이기 때문에 필요한게 있으면 그때그때 끌어다 쓰면 된다는 것이다. 이는 Dynamic Linking과 Dynamic Loading과도 연결되는 부분이다(여기 참고).
다시 정리해보자. 어떤 프로그램을 실행시키려면 실행되기 위한 최소한의 코드만 메인 메모리에 로딩시키면 된다. 그런데 우리는 '메모리 관리' 파트에서 '페이지'의 개념을 배웠다. 모든 프로그램은 페이지 단위로 조각화 되어있기 때문에, 프로그램 실행에 필요한 '페이지'만 메모리에 로딩되면 된다. 나머지 페이지는 필요할 때 로딩하면 된다. 이게 바로 Demand Paging의 개념이다.
Demand Paging
: 프로그램 실행 중에 필요한 페이지를 그때그때 로딩하는 방법. 사용하지 않는 페이지는 물리적 메모리에 로딩되지 않는다.
이해하기 쉽게 그림으로 살펴보자. 그림의 화살표는 일단 무시하자.
위 그림에서 가상 메모리의 페이지는 8개로 A~H 까지 있다. 그리고 모든 페이지는 SSD에 저장되어 있다. 현재 A, C, F 페이지만 메인 메모리 위에 올라가 있다. 이제 CPU는 프로그램 실행 중 페이지를 요구할 때, 메인 메모리에 이미 존재하는 페이지는 페이지 테이블을 통해 그대로 접근하면 되고, 메인 메모리에 존재하지 않는 페이지는 SSD에서 가져와서 쓰면 된다. 그런데 페이지 테이블에서 접근하고자 하는 페이지가 메인 메모리에 로딩되어 있는지, 로딩되어 있지 않은지는 어떻게 구분할 수 있을까? 이를 구분해 주는게 valid bit다.
valid bit : 해당 페이지가 메인 메모리에 존재하는지 알려주는 값으로 page table entry마다 있다.
1) valid bit = v (valid)
: 해당 페이지가 메인 메모리 위에 있다.
2) valid bit = i (invalid)
: 해당 페이지가 메인 메모리 위에 없다. 따라서 SSD에서 가져와야 한다. 이를 Page Fault라고 한다.
Page Fault가 발생하면 SSD에서 페이지를 가져와야 하기 때문에 소프트웨어 인터럽트(software interrupt)가 발생한다. 인터럽트가 발생하면 운영체제는 Page Fault를 아래와 같이 처리한다.
1. 페이지 테이블에서 valid bit 검사
2. 값이 i 면 page fault 이므로 trap 발생시킴
3. SSD 에서 필요한 페이지 탐색
4. 메인 메모리 free frame 에 로딩
5. 페이지 테이블에 valid bit를 v 로 수정
6. 명령 재수행
위 그림에서 Page Faule가 발생하면 SSD까지 갔다와야 하기 때문에 오버헤드가 발생한다. 따라서 Page Fault의 발생 비율은 페이징의 성능에 큰 영향을 미친다. 만약에 Page Fault가 발생하는 비율을 알 수 있다면, 수식을 통해 Demand Paging 성능을 도출해낼 수 있다. 식은 아래와 같다.
Effective Access Time(EAT) for Demand Paging
memory access time = M
page fault time = T = page fault overhead + swap page out + swap page in + restart overhead
page fault ratio = p (0 <= p <= 1)
Effective Access Time (EAT)
= { (1 - p) * M } + { p * T }
= { no page fault 일때 시간 } + { page fault 일때 시간 }
Page Fault Ratio(p)는 낮을수록 EAT 값이 단축되므로 p를 최대한 낮추는 것이 효율적이다. Page Fault는 크게 두 부류로 나눌 수 있다. 첫째는 free frame이 있는 경우고, 둘째는 free frame이 없는 경우다. p 값에 큰 영향을 미치는 것은 후자다. 왜냐하면 free frame이 있는 경우 그냥 할당하면 되지만 free frame이 없는 경우 메인 메모리에 있는 페이지를 하나 빼야하기 때문이다.
어떤 페이지를 뺄 것인지는 상당히 중요한 문제다. 앞으로 가장 안 쓰일 페이지를 빼는 것이 p 값을 낮추는데 도움 되기 때문이다. 다음턴에 쓸 페이지를 빼버리면 다음턴에 page fault가 또 발생하게 된다. 따라서 운영체제는 특정 알고리즘에 따라 교체할 페이지를 선택한다. 이를 '페이지 교체 알고리즘'이라고 한다.
기억해놓자. 페이지 교체 알고리즘을 사용하는 이유는? Page Fault Ratio를 최대한 낮추기 위해서!!
글이 좀 길어질거 같아서 페이지 교체 알고리즘은 다음 글에서 이어쓰도록 하겠다. 오늘의 학습목표를 달성했는지 점검해보자. 어떤 프로그램을 실행시키려고 하는데 물리적 메모리에 여유 공간이 없다면? Swapping과 Demand paging으로 해결 가능하다. Swapping은 프로세스를 통째로 바꿔치기 하는 방법이고, Demand paging은 필요한 페이지를 그때그때 끌어다 쓰는 방법이다. 물리적 메모리에 여유 공간이 없으면 메인 메모리에서 안 쓰일거 같은 페이지를 빼서 공간을 만들어 주면 되는데, 어떤 기준으로 빼는지는 다음 글에서 이어진다.
'CS > 운영체제' 카테고리의 다른 글
[ 운영체제 ] 쓰레싱(Thrashing)과 작업 공간(Working Set), 지역성(Locality) (1) | 2022.02.21 |
---|---|
[ 운영체제 ] 가상 메모리2 - Modify bit(Dirty bit), 페이지 교체 알고리즘 (2) | 2022.02.16 |
[ 운영체제 ] 메모리 관리3 - 페이징 단점, 내부 단편화, TLB, 세그멘테이션(Segmentation) (0) | 2022.02.09 |
[ 운영체제 ] 메모리 관리2 - 페이지 테이블의 세 가지 구조 (0) | 2022.02.08 |
[ 운영체제 ] 메모리 관리 1 - 페이징(Paging) (2) | 2022.02.04 |