페이징 시스템의 효과적인 실행을 위한 각종 고려사항.
프리페이징
💡 프로세스의 코드와 데이터를 필요한 시점에 미리 가져와 물리적 메모리에 적재하는 것
- 순수 요구 페이징이 가진 특성; 프로세스가 시작될 때 많은 수의 페이지 폴트가 발생하는 것을 방지하려는 시도
- 프리페이징을 사용하는 비용이 페이지 폴트를 처리하는 비용보다 적은지 따져봐야 함.
- 어떤 페이지를 쓸지도 명확하지 않다면, 프리페이징이 쉽지 않을 수 있음.
페이지 크기
페이지 크기를 결정하는데 참고할 사항
-
페이지 테이블의 크기
페이지 크기가 감소할수록, 페이지 테이블의 크기가 커진다.
모든 활성 프로세스는 자기만의 페이지 테이블이 필요.
이 관점에선 페이지가 클 수록 좋다.
-
할당해준 페이지 사용 효율
이 관점에서는 작은 페이지가 좋다.
할당한 메모리를 모두 사용한다는 보장이 없기 때문. (= 내부 단편화)
-
페이지의 읽고 쓰는 시간
페이지가 늘어날 수록, 읽고 쓰는 시간이 더 늘어난다.
페이지를 전송하는데 드는 시간은 페이지의 크기와 별 상관이 없다.
그러나, 작은 페이지에서는 지역성이 향상되어 전체 I/O는 더 줄어들 것이기 때문에 메모리 총량도 덜 쓴다는 이점이 있다.
그래서 이 관점에서는 작은 페이지가 더 낫다.
-
페이지 폴트 횟수
페이지 폴트를 줄이려면 큰 페이지가 좋다.
다만 시대적으로는 페이지 크기가 커지는 추세.
TLB Reach
💡 TLB로부터 액세스할 수 있는 메모리 공간의 크기
TLB의 크기를 결정하는 것 또한 필요하다.
- TLB에 사용되는 연관 메모리가 비싸고 전력을 많이 소모하기 때문.
이를 위해 TLB Reach를 쓰는데, 이는 TLB 속 항목 수에 페이지 크기를 곱한 것.
TLB Reach 늘리기
- TLB 크기 늘리기 → 아무리 늘려도 TLB에 다 안 들어가는 프로세스가 있다.
- 페이지 크기 늘리기 or 여러 페이지 크기를 제공
- 페이지 크기 늘리기 : 단편화가 증가할 수 있음.
- 그래서 여러 페이지 크기를 제공한다.
역 페이지 테이블
역 페이지 테이블이 전체 가상 주소 공간에 대한 정보를 유지하지는 않음.
- 참조된 페이지가 현재 메모리에 없을 때 문제가 됨
- 이 정보를 공급하기 위해서는 프로세스 당 하나씩 확장된 페이지 테이블을 유지해야 함.
확장된 페이지 테이블 = 원래 페이지 테이블과 같음.
- 그러나 이는 페이지 폴트 시에만 참조. 빨리 읽을 필요가 없다.
- 그러므로 그 자체가 페이징될 수도 있다.
- 읽어들일 때 또 다른 페이지 폴트를 부를 수 있으므로 커널에서 조심스럽게 처리해야 함.
프로그램 구조
사용자가 요구 페이징을 직접 다루는 방식을 생각해보자.
배열이 행 중심으로 저장되었다고 가정해보자.
for j in range(128):
for i in range(128):
arr[i][j] = 0;
이 경우 각 행이 한 페이지를 점유하게 됨.
따라서 페이지 폴트가 128^2번 나게 됨.
for i in range(128):
for j in range(128):
arr[i][j] = 0;
이 경우에는 페이지 폴트가 128번만 나게 됨.
즉, 자료구조와 코드의 구조를 잘 맞추면 지역성을 향상시킬 수 있음.
→ 페이지 폴트율과 작업 집합의 페이지 수를 줄일 수 있다는 이야기
컴파일러와 로더도 페이징에 큰 영향을 미칠 수 있음.
<컴파일러>
- 코드와 데이터를 분리하는 것, 재진입 코드를 생성하는 것을 코드 페이지를 읽기 전용으로 만들어 코드 페이지를 변경하지 않게 한다.
- 변경되지 않은 페이지는 교체 시 페이지 아웃 하지 않아도 된다.
<로더>
- 하나의 루틴을 페이지 경계에 걸치지 않게 하여 각 루틴이 한 페이지 안에 완전히 들어갈 수 있게 할 수 있음.
- 서로 호출하는 빈도가 잦은 루틴끼리는 서로 같은 페이지에 위치시키기
I/O 상호 잠금
요구 페이징을 사용할 때, 그 페이지의 일부를 메모리에 고정하는 것이 필요.
이 상황은 I/O가 사용자 공간에서 이뤄질 때 발생.
- I/O는 별도의 I/O 처리기에서 실행
그러나 다음과 같은 이벤트가 일어나면 안됨.
- 어떠한 프로세스가 I/O를 요구
- CPU는 다른 프로세스에 할당
- 갑자기 이 프로세스가 페이지 폴트를 일으키고, 대기 중인 프로세서의 버퍼 메모리를 포함한 페이지를 교체
- 그 페이지는 페이지 아웃
- 시간이 흐르고, I/O 작업 처리.
- 그치만 원래 버퍼가 있는 프레임은 이미 타 프로세스가 사용
이를 막기 위해 크게 2가지 방법이 있음.
- 사용자 공간에서는 I/O를 하지 않음.
- 실제 I/O는 시스템 공간과 장치 사이에서만 함
- 데이터 : I/O → 시스템 공간 → 사용자 공간
- 오버헤드 발생 가능성이 높아짐.
- 페이지를 메모리에서 잠금하는 것.
- 잠금 비트를 프레임마다 두고, 만약 프레임이 잠기면 교체 대상에서 제외하는 방식
- 디스크에 블록을 쓰기 위해서는 해당 블록을 담고 있는 페이지를 일단 잠그고, I/O가 끝나면 풀어줌.
잠금 비트를 사용하는 사례
- 운영체제 커널의 일부나 전체를 메모리에 잠근다.
- 사용자 프로세스를 잠근다. (ex. 데이터베이스 프로세스)
이러한 페이지 고정을 위한 시스템 콜이 운영체제마다 존재.
한편, 페이지 고정은 악용될 수 있으며 메모리 관리 알고리즘에 부담을 줌.
메모리 고정 요청은 앱이 직접 특권을 가져야 함.
잠금 비트 사용이 위험한 경우
- 잠금 비트가 해제되지 않는 경우 : 이 경우 잠긴 프레임을 사용할 수 없다.