CS 전공/OS

[운영체제] 11. Demand Paging

Easyho.log 2024. 6. 23. 23:55

1. 물리 메모리와 가상 메모리

1) 주소 공간과 물리 메모리

컴퓨터에 설치할 수 있는 물리 메모리에도 한계가 있다. -> 물리 메모리는 CPU의 주소 버스 크기에 달려 있기 때문이다. 32비트 CPU의 최대 물리 메모리의 양은 4GB, 64비트 CPU의 최대 물리 메모리 양은 16EB이다. 하지만 컴퓨터의 실제 물리 메모리는 CPU의 최대 메모리에 미치지 못한다. 비용이 많이 들기 때문이다. 현재 대부분의 컴퓨터의 물리 메모리 양은 8GB ~ 32GB이다. 또한, 프로세스는 자신이 최대 용량을 독점한다고 생각한다. 이러면 어떠한 문제가 발생할까?

2) 물리 메모리의 한계

물리 메모리의 한계에서 얻을 수 있는 질문은 다음과 같다.

1) 설치된 물리 메모리보다 더 큰 프로세스를 실행시킬 수 있는가?

2) 프로세스들을 합친 크기가 설치된 물리 메모리보다 클 때 이들을 실행시킬 수 있는가?

 

여기에 숨겨진 전제는 다음과 같다.

1) 프로세스 전체가 적재되어야 실행이 가능한가?

2) 당장 실행에 필요한 프로세스의 일부 메모리만 적재한 채 실행시킬 수 없는가?

3) 가상 메모리

- 물리 메모리 크기 한계 극복 해결책이다. -> 물리 메모리를 디스크 공간으로 확장한다.

- 프로세스를 물리 메모리와 하드 디스크에 나누어서 저장한다.

- 프로세스나 사용자가 프로세스를 실행하기에 충분히 큰 메모리가 있다고 착각하게 만드는 메모리 관리 기술이다.

 

** 스와핑 **

- 메모리가 부족할 때, 실행에 필요하지 않는 부분은 하드 디스크로 이동하고

- 실행에 필요할 때, 하드 디스크로부터 물리 메모리로 이동한다.

4) 개념

- 운영 체제는 물리 메모리 영역을 하드 디스크까지 연장

- 프로세스의 실행 시 프로세스 전체그 물리 메모리에 적재되어 있을 필요가 없다. (대전제)

- 물리 메모리의 빈 영역이 부족하게 되면, 물리 메모리의 일부분을 하드 디스크로 옮겨 물리 메모리의 빈 영역을 확보한다.

- 물리 메모리를 확장하여 사용하는 디스크 영역 : 스왑 영역

- 사용자는 컴퓨터 시스템의 무한대의 메모리가 있는 것으로 착각

5) 메모리에 대한 각 시스템들의 관계

1. 사용자나 프로세스

- 무한대에 가까운 메모리를 사용하며, 0번지부터 연속되어 프로세스가 적재되는 것으로 생각

- 가상의 전체 메모리가 있다고 생각함

2. 운영체제 : 프로세스 일부만 물리 메모리에 적재

3. 디스크 : 없는 메모리가 있는 메모리처럼 사용하게 해줌


2. Demand-Paging

1) 가상 메모리를 만드는 방법

>> 요구 페이징 : 페이징 기법을 토대로 프로세스의 일부 페이지들만 메모리에 할당하고, 페이지가 필요할 때 메모리를 할당받고 페이지를 적재시키는 메모리 관리 기법이다. 현재 실행에 필요한 일부 페이지만 메모리에 적재하고 나머지는 하드 디스크에 두고, 특정 페이지가 필요할 때 메모리에 적재하는 방식이다.

2) Swap Area과 페이지 테이블 엔트리

- 스왑 영역 : 메모리가 부족할 때, 메모리를 비우고 페이지를 저장해두는 하드 디스크의 영역

- 페이지 테이블 엔트리

3) Page Fault

메모리를 참조하려는데 물리 메모리에 원하는 페이지가 없을 때 페이지 폴트가 발생한다.

- CPU가 액세스하려는 페이지가 물리 메모리에 없을 때, 페이지 폴트가 발생한다.

- 페이지 폴트가 일어나면 빈 프레임을 할당하고 스왑 영역이나 실행 파일로부터 페이지를 적재한다.

- 더 자세한 처리 과정

1) 프로세스가 페이지 N을 요청할 때, 페이지 테이블의 유효 비트가 0이면 페이지 폴트가 발생한다.

2) MMU는 PTE에 기재된 블록번호에 접근하여, 해당 데이터를 메모리의 빈 프레임으로 가져온다. -> 비어 있는 공간이 없으면 페이지 교체 알고리즘이 동작한다.

3) 해당 프레임으로 접근하여 해당 데이터를 프로세스에 넘긴다.

4) 유효비트를 1로 업데이트하고, 프레임 번호도 업데이트한다.

4) 가용 프레임 리스트

- 비어 있는 프레임들은 OS가 리스트 형태로 관리한다.

- 그리고 보안을 위해 할당시에는 값들을 0으로 초기화한다.

5) 프로세스 실행 방식

1. 프로세스가 실행을 시작할 때 첫 페이지 메모리에 적재한다.

2. 페이지 폴트를 통해 실행 파일로부터 페이지들 적재

3. 메모리가 부족하면 스왑아웃/스왑인

4. 스왑-아웃된 페이지 100의 스왑-인 후 n++ 실행

5. 수정된 페이지를 스왑 영역에 쓰기

-> fork(), exec() 시스템 콜까지 호출하면 굉장히 낭비가 심하다.

6) Copy On Write (COW)

쓰기 시 복사이다.

- 자식 프로세스를 위해 부모 프로세스의 페이지 테이블만 복사한다.

- 자식 프로세스는 초기에 부모 프로세스의 메모리 프레임을 완전 공유한다.

- 자식 프로세스의 페이지 테이블 항목에 '쓰기 시 복사'를 표시한다.

- 자식이나 부모 중 누군가 페이지를 수정할 때, 그때 새로운 프레임을 할당 받아 내용을 수정하고 프레임 번호를 업데이트한다.

-> 페이지 테이블 하나만 복사해도 새로운 프로세스가 하나 더 생성된다는 것이다.

 

** 장점 **

1. 프로세스 생성 시간이 절약된다 -> 부모 프로세스의 페이지 테이블만 복사

2. 메모리가 절약된다. -> 읽기만 하는 페이지는 새로은 프레임을 할당할 필요가 없다.


3. 페이지 교체 알고리즘

1) 지역성 Remind

- 기억장치에 접근하는 패턴이 메모리 전체에 고루 분포되는 것이 아니라 특정 영역에 집중되는 성질

-> 프로세스는 최근에 참조한 데이터와 코드를 다시 참조하는 경향성이 있다!

- 공간의 지역성과 시간의 지역성이 있다.

2) Working Set (작업 집합)

- 일정 시간 범위 내에 프로세스가 액세스한 페이지들의 집합이다.

- 페이지 폴트는 작업 집합을 메모리에 적재하는 과정이다.

  • 참조의 지역성으로 인해 일정 시간 내에 작업 집합을 형성한다.
  • 시간 범위가 클수록 작업 집합도 크다.

- 참조의 지역성 → 페이지 폴트 → 메모리에 작업 집합 형성

- 즉, 일정 실행시간동안 참조한 페이지의 집합이라고 할 수 있다.

- 이동도 가능하다 → 프로세스가 실행되는 동안 작업 집합이 이동한다.

3) 페이지 교체

- 메모리 프레임 중 하나를 선택하여 비우고 이곳에 요청된 페이지를 적재하는 과정

→ 스왑 영역으로 보낼 페이지를 결정하는 알고리즘

→ 요청된 페이지가 메모리 프레임에 없고, 요청된 페이지를 적재할 빈 프레임도 없는 경우

- 페이지 폴트 핸들러에서 실행되는 작업이다.

→ 희생 프레임 : 비우기로 선택된 프레임

→ 희생 페이지 : 희생 프레임 안에 있는 페이지

→ 희생 페이지는 스왑 아웃되고 요청 페이지가 스왑 인 된다.

- 현재 작업 집합에 포함되지 않거나 가까운 미래에 참조되지 않을 페이지를 희생 페이지로 선택

→ 지역 교체와 전역 교체가 있다.

4) 희생 프레임 선택 범위

1. 지역 교체

- 프로세스 별로 독립적으로 페이지 폴트를 처리한다.

- 요청한 프로세스에게 할당된 프레임 중에서 희생 프레임을 선택한다.

- 한 프로세스에서 발생한 스레싱이 다른 프로세스로 전파되지 않는다.

2. 전역 교체

- 전체 메모리 프레임 중에서 선택한다.

- 지역 교체보다 효과적이라고 한다.

- 많은 운영체제 (Ex, Linux, Windows) 에서 사용된다.

5) 페이지 교체 알고리즘

1. 최적 페이지 교체 알고리즘 

최적 페이지 교체 알고리즘

-> 앞으로 사용할 페이지를 미리 살펴보고 교체 페이지 선정 

-> 현실적으로 불가능하다

-> 성공 : 5, 폴트 : 5

 

2. FIFO

FIFO

-> 가장 먼저 들어온 페이지를 교체 대상 페이지로 선정한다.

-> 성능이 떨어진다.

 

3. Second Chance Algorithm 

- FIFO의 변형 버젼

- 페이지가 히트가 되면 후순위로 밀려나며 한 번 더 사용

Second Chance Algorithm

 

 4. Clock Algorithm

- 원형 큐를 사용한다.

- 스왑 영역으로 옮길 대상 페이지를 가리키는 포인터를 사용한다.

- 성공적으로 참조가 될 시 0 -> 1로 값을 변경한다.

- 대상 포인터가 있는데 이는 교체될 페이지를 의미한다. 페이지가 교체되면 대상 포인터를 밑으로 이동한다. 참조 비트가 1인 페이지는 0으로 만든 후 건너 뛴다.

Clock Algorithm

 

5. LRU and LFU

i) LRU : Least Recently Used : 가장 오래전에 쓰인 페이지 교체

LRU

ii) LFU : Least Frequently Used

LFU

-> 셋 다 사용 횟수가 같으면 맨 앞의 페이지를 교체한다.

 

6. NRU (Not Recently Used)

: 최근 미사용 교체 알고리즘이다.

- 대상 페이지를 찾을 때 참조 비트가 0인 페이지를 먼저 찾고 없으면 변경 비트가 0인 페이지를 찾는다.

 

하지만 교체가 비효율적이면 Page Fault가 계속 날 것이다. 계속 연달아서 날 것이다.

또한, page fault가 계속되면 처리 도중 CPU는 놀것이다.

이런 악순환이 반복되는 현상을 쓰래싱이라고 한다.

6) 스래싱

하드 디스크의 입출력이 너무 많아져서 잦은 페이지 부재로 작업이 멈춘 것 같은 상태이다. 디스트 I/O가 급격하게 증가한다.

- 해결 방법

1. 다중 프로그래밍 정도 줄이기

2. 하드 디스크 대신 빠른 SSD 사용

3. 메모리 늘리기

4. 프로세스별로 프레임을 적당히 분배하기


4. 프레임 할당 문제

1) 프레임 할당

페이지 폴트와 스래싱을 줄이기 위한 알고리즘이다.

 

1. 정적 할당

- 균등 할당 : 프로세스에게 크기에 관계없이 동일한 개수의 프레임 할당. 단순하지만 작은 프로세스에게는 프레임 낭비이다.

- 비례 할당 : 많이 필요한 프로세스에게 많은 프레임 할당. 실행 중에 프로세스의 크기를 알기 쉽지 않다는 단점