이화여자대학교 컴퓨터공학과 반효경 교수님의 "운영체제 (KOCW)" 강의를 필기한 내용입니다.
다소 잘못된 내용과 구어적 표현 이 포함되어 있을 수 있습니다.
문서를 이전하는 과정에서, 이미지 데이터가 유실되어 문서상에 보이지 않습니다.
Demand Paging
-
얘는 페이지를 모두 메모리에 올리는 것이 페이지가 필요한 시점에 메모리에 올리는 방법을 의미한다
-
장점은
- IO 감소
- 한번 올릴때 페이지 단위로 올리니까
- Memory 사용량 감소
- 필요한 페이지만 올리니까 예외처리코드같은 자주 실행되지 않는 코드들이 메모리에 불필요하게 올라가지 않음
- 빠른 응답시간
- 여러개의 프로세스가 작동하는 경우에 하나의 프로세스 전체가 메모리에 올라가고 나머지는 아주 일부분만 올라간다면 모두 올라와있는 놈은 빠르지만 나머지는 IO 가 많아져 느림
- 하지만 Demand Paging 을 사용하면 각 프로세스의 필요한 부분만 올라와있기 때문에 프로세스 전체가 메모리에 올라와있는 것보다는 느릴 수 있겠지만 전체적인 응답시간은 빨라진다
- 더 많은 사용자 수용
- 프로세스당 실시간으로 사용하는 메모리의 양이 적으므로
- IO 감소
-
그래서 프로세스가 메모리에 올라가게 되는 전체적인 모습을 보면 아래와 같다
(사진 사라짐)
- 제일 왼쪽은 가상 메모리 공간을 할당받고 프로세스가 페이지별로 나뉘어진 모습이다
- A ~ F 까지는 가상 메모리 공간에서 프로세스가 실제로 차지하는 페이지들이고
- G ~ H 는 프로세스가 차지하지 않는 빈 페이지임
- 그리고 오른쪽의 두 그림처럼 메모리에 적재되었다고 한다면
- 페이지 A, C, F 만 Demand Paging 에 의해 실제 메모리에 적재되었고
- 나머지 페이지들은 디스크에 스왑되어있는 상황
- 그때 Page Table 은 왼쪽 두번째와 같다
- 실제 메모리에 적재되어있는 페이지는 프레임 번호가 적히고 Valid 로 표시된다
- 그리고 적재되어있지 않는 페이지는 Invalid 로 표시된다
- 가상 메모리 공간에서 프로세스가 차지하지 않는 빈 페이지도 Invalid 로 표시됨
- 당연한 이야기지만 프로세스가 처음 생성되었을때에는 Page Table 이 전부 Invalid 로 표시되어 있고 프로세스가 실행됨에 따라 필요한 페이지가 차츰 올라가며 Valid 로 바뀌게 된다
- 제일 왼쪽은 가상 메모리 공간을 할당받고 프로세스가 페이지별로 나뉘어진 모습이다
Page Fault
-
근데 Demand Paging 을 하려면 어떤 페이지가 필요해서 OS 에 올려달라고 요청할 수 있어야 되는데 이를 위한 것이 바로 Page Fault 이다
-
간단히 말하면 MMU 가 주소를 바꿀때 해당 주소가 Invalid 한 페이지에 있다면 트랩을 걸어 OS 로 하여금 해당 페이지를 적재할 수 있도록 하는 것
-
Page Fault 의 처리 과정은 다음과 같다
(사진 사라짐)
- Invalid 페이지를 참조
- MMU 는 이때 유효한 주소인지, Protection Violation 등이 없는지 추가적으로 체크한다
- (MMU 에 의해) Page Fault Trap 이 걸려서 OS 로 CPU가 넘어감
- Invalid 페이지를 참조
-
실제 메모리에서 비어있는 프레임 (Free Frame) 을 할당함 → 이미 모든 프레임이 하나 사용중이면 하나를 디스크로 스왑시켜서 빈 프레임을 만들어낸다
- 디스크에서 해당 페이지를 가져오고
- 빈 프레임에다가 페이지를 채움
- 3, 4번 과정은 Disk IO 과정이기 때문에 당연히 해당 프로세스는 Block 되어 다른 프로세스로 CPU 가 넘어간다
- Page Table 에다가 Frame 번호 및 Valid/Invalid 를 업데이트함
- Ready 상태로 있다가 CPU 를 받으면 멈췄던 Instruction 부터 다시 실행
Page Fault Rate
(사진 사라짐)
- Page Fault Rate
p
를 위와 같이 정의한다면- 즉, 0이면 Page Fault 가 절대 나지 않음
- 1이면 모든 참조에서 Page Fault 가 발생
- p 는 실제 시스템에서 0.01 정도로 아주 낮게 나온다 → Page Fault 가 앵간하면 일어나지 않는다는 의미
Page Replacement
- 위에서 Page Fault 루틴 설명할 때 빈 프레임이 없으면 기존의 프레임에 있는 페이지를 swap out 시켜서 빈 프레임을 만들어낸다고 했는데 그것을 Page Replacement 라고 한다
(사진 사라짐)
- 위 그림이 Page Replacement 의 과정인데
- 희생양을 정하고 Swap out 한다
- 이때는 페이지에 변화가 없을 때에는 그냥 냅둬서 Overwrite 되게 할 수 있지만
- 만일 페이지 내용에 변화가 있을 때에는 변화된 내용을 디스크에 반영해주는 IO 가 필요하다
- Page Table 에서 Swap out 한 페이지의 Validity 를 업데이트한다
- 요청된 페이지를 Swap in 한다
- Page Table 에서 Swap in 한 페이지의 Validity 를 업데이트한다
- 희생양을 정하고 Swap out 한다
- 당연히 Page Replacement 를 할 때에는 Page Fault Rate 가 최소화되도록 프레임을 선택해야 되는데
- 이것을 위한 알고리즘이 Replacement Algorithm 이다
Optimal Algorithm (Belady’s Algorithm)
-
다시는 참조되지 않거나 가장 먼 미래에 참조될 페이지를 Replace 하자는 생각
-
하지만 미래의 일은 알 수 없기 때문에 비현실적이다 → 이에 따라 Optimal Offline Algorithm 이라고도 불림
-
다만, 이 알고리즘이 Page Fault 를 최소화한다는 것이 증명되어 있으므로 다른 알고리즘들의 성능에 대한 척도를 제공해주는 역할을 한다
-
아래의 예제를 보면
(사진 사라짐)
- 위 시나리오에서 일단 첫 4번은 어쩔 수 없다 → 페이지가 없으니 어쩔 수 없이 Page Fault 가 발생
- 5번째 Page Fault 에서는 4번 페이지가 가장 나중에 사용되므로 4번이 5번으로 Replace
- 6번째 Page Fault 에서는 5번만 나중에 사용되므로 사용되지 않는 페이지 아무거나 Replace
FIFO (First In First Out) Algorithm
-
선입선출이다
-
얘는 FIFO (혹은 Belady’s) Anomaly 라는게 있는데 이게 뭐냐면
- 일반적으로 Frame 수가 늘어나면 Page Fault 는 줄어드는 것이 일반적인데
- FIFO 방식을 사용하면 Frame 수가 늘어났을 때 Page Fault 가 늘어날 수도 있다는 것이다
- 아래 예시 보면 됨
(사진 사라짐)
LRU, LFU Algorithm
LRU (Least Recently Used) Algorithm
-
가장 오래전에 참조된 것을 지우는 것
-
최근에 참조된 것이 다시 참조될 가능성이 높다는 성질을 이용
-
FIFO 와의 차이점은 FIFO 의 경우 가장 오래전에 입장한놈을 지운다면 LRU 는 가장 오래전에 마지막으로 참조된 것을 지운다
(사진 사라짐)
LFU (Least Frequently Used) Algorithm
- 가장 덜 빈번하게 참조된 것을 지우는 것
- 빈번하게 참조된 것이 다시 참조될 가능성이 높다는 성질을 이용
LRU vs LFU
(사진 사라짐)
- LRU 랑 LFU 의 장단점을 극단적으로 보여주기 위한 예시인데 누가 개같이 쫒겨날지는 직접 해보면 알 수 있음
- 이걸 토대로 LRU 랑 LFU 를 비교해보면
- LRU 는 제일 나중에 참조된 것을 내쫒긴 하지만 그놈이 제일 많이 참조된 놈이어서 참조 빈도에 대한 고려는 안된다는 단점이 있고
- LFU 는 제일 적게 참도된 놈을 내쫒았는데 마지막 참조 시점의 고려가 되지 않는다는 단점이 있다
- 위의 예시에서는 하필 그놈이 제일 최근에 들어온 놈이어서 연속 참조에 장애가 걸리는 문제가 발생한다
구현
(사진 사라짐)
- LRU: 얘는 Linked List 형태로 구현한다
- 즉, 참조되면 그놈을 제일 아래로 내려 제일 높은 우선순위를 갖게 하고
- 내쫒을때는 제일 위에 있는 제일 낮은 우선순위를 내쫒음
- 따라서 시간복잡도는 O(1) 이 됨
- LFU: 얘는 Heap 을 이용하여 구현한다
- 참조 시점이 아니라 빈도가 중요하므로 다른 놈들과의 비교를 해야되는데
- 비교할때는 Linked List 를 이용해 일렬로 비교하며 따라가는 것 보다는 Heap 을 이용해 Leaf 까지 따라가며 비교횟수를 줄이는 것이 좋기 때문
한계
- 실제로는 LRU, LFU 알고리즘을 이용해 Page Replacement 를 할 수는 없다
- 왜냐하면 MMU 가 하드웨어 유닛이기 때문에 Page Reference 는 OS 의 관여 없이 기계적으로 일어나기 때문
- OS 가 관여하는 부분은 Page Fault 가 발생했을 당시이므로 어떤 페이지가 언제 혹은 얼마나 참조되었는지는 OS 가 알 수 없다
Clock Algorithm
-
위에서 제시한 LRU, LFU 알고리즘의 한계를 극복하기 위해 등장한 알고리즘
-
다음과 같이 작동한다
(사진 사라짐)
- 일단 시계에서 네모는 각 페이지를 의미한다
- 그리고 숫자는 Reference Bit 으로, 최근에 해당 페이지가 참조되었음을 나타낸다
- Reference Bit 은 MMU 에 의해 1로 바뀌고 OS 에 의해 0으로 바뀐다
- Page Fault 가 발생하면 OS 는 시계방향으로 Reference Bit 가 0인 페이지를 찾는다
- Reference Bit 가 1이라면 OS 가 0으로 바꾸고 다음 페이지로 넘어간다
- Reference Bit 이 0인 페이지를 찾으면 해당 페이지를 Swap out 한다
-
이렇게 하면 다음과 같은 효과가 난다
- Page Fault 가 일어나지 않는 동안은 MMU 가 Reference Bit 을 관리하며 참조되었던 페이지들을 표시한다
- Page Fault 가 일어나면 OS 가 MMU 가 표시한 Reference Bit 을 이용해 참조되지 않았던 페이지를 찾아 swap out 한다
- 이때 swap out 되는 페이지는 OS 에 의해 0으로 바뀐 뒤에 시침이 한바퀴를 돌아 다시 돌아올 때 까지 한번도 참조되지 않았던 것이 보장되므로 충분히 옛날에 마지막으로 참조되었던 것으로 생각할 수 있다
- 따라서 이것은 LRU 와 비슷하다고 할 수 있다
- 즉, LRU 의 근사 (approximation) 알고리즘
- 공통점 → 마지막 참조 시점을 기준으로 페이지를 고름
- 차이점 → 마지막 참조 시점이 가장 오래된 놈이라고 할 수는 없음
-
이놈은 다음과 같은 이름으로도 불린다
- Second Chance Algorithm: Reference Bit 이 1이면 한번 봐주고 다음 페이지로 넘어감
- NUR(Not Used Recently) 혹은 NRU(Not Recently Used): LRU 에서 Least 가 Not 으로 바뀜
-
Reference Bit 이외에도 Modified Bit 을 이용해 더욱 개선할 수도 있다
- Modified Bit (Dirty Bit) 을 이용해 페이지가 변경되지 않았으면 IO 없이 swap out 하여 Overwrite 되게 함
Page Frame Allocation
- 이것은 프로세스 하나에게 몇개의 Frame 을 할당할 것이냐인데
- 이것이 중요한 이유는 다음과 같다
- 프로세스는 실행코드 말고도 데이터와 협력해야되는 경우가 많으므로 여러 페이지에 동시에 참조할 일이 빈번하다
- 또한 Loop 의 경우에는 해당 코드를 담은 페이지가 전부 올라와 있어야 Page Fault 가 안난다
- 만약 Frame Allocation 이 2개인데 Loop 의 코드가 3 frame 을 필요로 한다면 1개의 페이지가 계속해서 Page Fault 가 날 것이기 때문
- 다음과 같은 방법으로 할당할 수 있다
- Equal Allocation: 모두 똑같은 개수 할당
- Proportional Allocation: 프로세스 크기에 따라 할당
- Priority Allocation: CPU 우선순위에 따라 할당
- 이렇게 할당해 놓고 Replace 를 할때에는 해당 프로세스의 페이지 내에서만 Replace 되게 하는 방법을 Local Replacement 라고 한다
- 하지만 프레임의 개수를 할당하지 않고 Replace Algorithm 에 따라 프로세스간 프레임을 경쟁하도록 하여 프레임 할당을 유동적으로 관리하는 것을 Global Replacement 라고 한다
- 이렇게 하면 자연스레 프레임을 많이 필요로 하는 프로세스는 다른 프로세스의 페이지를 방출시켜 많이 차지하게 하고 해당 프로세스가 종료되면 자연스레 방출되어 다른 프로세스가 프레임을 차지할 수 있도록 할 수 있다
Thrashing
(사진 사라짐)
- 일반적으로 메모리에 많은 프로세스가 올라오면 (= Degree of Multiprogramming 이 증가하면) CPU Utilization 은 올라간다
- 하지만 어느 수준이 되면 프로세스 하나당 충분한 프레임이 확보되지 않아 Page Fault 가 너무 빈번하게 일어나 CPU Utilization 이 떨어지게 된다 → 이 시점을 Thrashing 이라고 한다
- 이 구간에는 CPU Utilization 이 낮아 OS 가 더 많은 프로세스를 메모리에 올리려고 하고, 그러면 Page Fault 가 더 빈번하게 일어나는 악순환이 계속됨
- 따라서 이것을 막기 위해서는 Degree of Multiprogramming 을 조절할 필요가 있다
Working Set Algorithm
-
페이지를 참조할때는 특정 시점에 빈번하게 참조하는 페이지가 한정되어있다는 Locality 에 착안해서
-
빈번하게 참조하는 페이지들의 집합을 Working Set 이라고 부르고 WS 의 크기가 할당된 프레임의 개수보다 크면 그냥 해당 프로세스 전체를 Swap out 시켜버리는 알고리즘이다
(사진 사라짐)
-
저 WS 를 구하기 위해 Working Set Window 라는 것을 이용하는 데 이것은 페이지 참조 시퀀스에서 특정 시점의 최근 n 개의 참조 페이지를 의미한다
- 위 그림의 예시로는 n 이 10이라고 할 수 있는 것
- 이 Working Set Window 만큼의 페이지들을 집합으로 만들어 그의 개수를 기준으로 프로세스를 방출할지 말지 결정하는 알고리즘
PFF (Page-Fault Frequency) Scheme
(사진 사라짐)
- 얘는 Page Fault Frequency 를 추적해서 Page Fault Rate 가 일정 수준이 유지될 수 있도록 하는 것이다
- 그래서 위 그림에서 보이는 것 처럼 상한 (Upper Bound) 와 하한 (Lower Bound) 를 정해놓고 상한보다 올라가면 프레임 할당을 더 증가시키고 하한보다 내려가면 프레임 할당을 줄여주는 방식
Page Size
- Page 사이즈가 너무 작다면
- 장점
- Internal Fragmentation 의 감소
- 필요한 정보만 메모리에 올라옴
- 단점
- 페이지 테이블 크기가 증가
- Disk Transfer 의 효율성 감소 (디스크에서 데이터를 찾는 것에서의 효율성)
- 장점
- 요즘 트랜드는 Page 사이즈를 크게 하는 것이랜다 (현재는 4Kb 정도)