Last update: @1/7/2023
•
가상 메모리(virtual memory)
: 실행하고자 하는 프로그램을 일부만 메모리에 적재하여 실제 물리 메모리 크기보다 더 큰 프로세스를 실행할 수 있게 하는 기술
◦
크게 페이징과 세그멘테이션이 있지만 여기선 대부분의 현대 운영체제가 사용하는 페이징만 다룸
◦
페이징 기법을 이용하면 물리 메모리보다 큰 프로세스를 실행할 수 있을 뿐만 아니라 앞선 절에서 배운 외부 단편화 문제도 해결할 수 있음
◦
페이징(paging)
: 프로세스의 논리 주소 공간을 페이지(page)라는 일정한 단위로 자르고, 메모리 물리 주소 공간을 프레임(frame)이라는 페이지와 동일한 크기의 일정한 단위로 자른 뒤 페이지를 프레임에 할당하는 가상 메모리 관리 기법
▪
페이징에서도 스와핑을 사용할 수 있음. 페이징을 사용하는 시스템에서는 프로세스 전체가 스왑 아웃/스왑 인되는 것이 아닌 페이지 단위로 스왑 아웃/스왑 인 됨
•
페이징 시스템에서의 스왑 아웃은 페이지 아웃(page out), 스왑 인은 페이지 인(page in)이라고 부르기도 함
•
프로세스를 이루는 페이지 중 실행에 필요한 일부 페이지만을 메모리에 적재하고, 당장 실행에 필요하지 않은 페이지들은 보조기억장치에 남겨둠으로써 물리 메모리보다 더 큰 프로세스를 실행할 수 있음
▪
프로세스가 메모리에 불연속적으로 배치됨으로써 순차적인 실행이 어려워짐. 프로세스를 이루를 페이지가 어느 프레임에 적재되어 있는지 CPU가 모두 알고 있기 어렵기 때문
▪
이를 해결하기 위해 페이징 시스템은 프로세스가 비록 (실제 메모리 내의 주소인) 물리 주소에 불연속적으로 배치되더라도 (CPU가 바라보는 주소인) 논리 주소에는 연속적으로 배치되도록 페이지 테이블(page table)을 이용함
•
페이지 테이블
: 페이지 테이블은 페이지 번호와 프레임 번호를 짝지어 주는 일종의 이정표로, 현재 어떤 페이지가 어떤 프레임에 할당되었는지를 알려줌
•
비록 물리 주소상에서는 프로세스들이 분산되어 저장되어 있더라도 CPU 입장에서 바라본 논리 주소는 연속적으로 보이기 때문에 프로세스들이 메모리에 분산되어 저장되어 있더라도 CPU는 논리 주소를 그저 순차적으로 실행하면 됨
▪
내부 단편화(internal fragmentation)
: 프레임 크기보다 작은 페이지를 적재할 때 내부에 낭비되는 공간이 남는 것
•
내부 단편화 문제를 줄이기 위해 페이지 크기를 너무 줄여버리면 반대로 페이지 테이블이 너무 커짐
•
따라서 적당한 크기의 페이지 크기를 정하는 것이 중요함
▪
대형 페이지(huge page)
: 기본적으로 설정된 페이지보다 큰 페이지
▪
각 프로세스의 페이지 테이블들은 메모리에 적재되어 있음. 이 페이지 테이블은 각 프로세스의 PCB에 기록됨
•
CPU 내의 페이지 테이블 베이스 레지스터(PTBR; Page Table Base Register)는 각 프로세스의 페이지 테이블이 적재된 주소를 가리키고, 프로세스의 문맥 교환이 일어날 때 다른 레지스터와 마찬가지로 함께 변경됨
•
하지만 테이블을 메모리에 두면 접근시간이 두 배로 늘어남. 테이블을 확인하러 한 번, 테이블의 주소를 보고 프레임을 확인하러 또 한 번 접근하기 때문
◦
이 문제를 해결하기 위해 CPU 곁에(일반적으로 MMU 내에) TLB(Translation Lookaside Buffer)라는 페이지 테이블의 캐시 메모리를 둠
▪
TLB는 페이지 테이블의 캐시이기 때문에 페이지 테이블의 일부 내용을 저장하고, 특히 참조 지역성에 근거해 주로 최근에 사용된 페이지 위주로 가져와 저장함
•
TLB 히트(TLB hit)
: CPU가 발생한 논리 주소에 대한 페이지 번호가 TLB에 있을 경우
•
TLB 미스(TLB miss)
: CPU가 발생한 논리 주소에 대한 페이지 번호가 TLB에 없는 경우. 메모리 내의 페이지 테이블에 접근할 수밖에 없게 됨
▪
페이징에서의 주소 변환
•
하나의 페이지(프레임)은 여러 주소를 포괄하고 있기 때문에 특정 주소에 접근하려면 페이지의 번호(page number)와 변위(offset)를 알아야 하고, 모든 논리 주소가 이 두 가지로 이루어짐
◦
가령 CPU가 32비트 주소를 내보냈다면 이중 N비트는 페이지 번호, 32-N 비트는 변위
◦
이 논리 주소 <페이지, 변위>는 페이지 테이블을 거쳐 물리 주소 <프레임 번호, 변위>로 변환됨. 이때 논리 주소와 물리 주소의 변위는 같음
▪
페이지 테이블 엔트리(PTE; Page Table Entry)
: 페이지 테이블의 각각의 행을 뜻하고, 페이지 번호, 프레임 번호 외에 아래 정보들로 이루어짐
•
유효 비트(valid bit)
: 현재 해당 페이지에 접근 가능한지 여부를 알려줌
◦
1: 메모리에 적재되어 있음
◦
0: 스왑 아웃 되어 보조기억장치에 있음
▪
이 페이지로 접근할 때 페이지 폴트(page fault)라는 예외가 발생하고, CPU는 이 페이지 폴트를 아래처럼 하드웨어 인터럽트와 비슷하게 처리함
•
CPU는 기존의 작업 내역을 백업함
•
페이지 폴트 처리 루틴을 실행함
•
페이지 처리 루틴은 원하는 페이지를 메모리로 가져온 뒤 유효 비트를 1로 변경
•
페이지 폴트를 처리했다면 이제 CPU는 해당 페이지에 접근할 수 있게 됨
•
보호 비트(protection bit)
: 페이지 보호 기능을 위해 존재하는 비트로, 해당 페이지가 읽고 쓰기가 모두 가능한 페이지인지, 혹은 읽기만 가능한 페이지인지를 나타냄
◦
1: 읽고 쓰기가 모두 가능한 페이지
◦
0: 읽기만 가능한 페이지(특히 코드 영역)
▪
읽기 전용의 페이지에 쓰기를 시도하면 운영체제가 이를 막아줌으로써 페이지를 보호함
◦
보호 비트는 r(Read), w(Write), x(eXecute)의 세 가지로 읽기, 쓰기, 실행 권한을 나눠서 표시할 수도 있음
•
참조 비트(reference bit)
: CPU가 이 페이지에 접근한 적이 있는지 여부를 나타냄
◦
1: 적재 이후 CPU가 읽거나 쓴 페이지
◦
0: 적재 이후 한 번도 읽거나 쓴 적이 없는 페이지
•
수정 비트(modified bit = dirty bit)
: 해당 페이지에 데이터를 쓴 적이 있는지 없는지 수정 여부를 알려줌
◦
1: 변경된 적이 있는 페이지
◦
0: 변경된 적이 없는 페이지(한 번도 접근한 적이 없거나 읽기만 했던 페이지)
▪
페이지가 메모리에서 사라질 때 보조기억장치에 쓰기 작업을 해야 하는지, 할 필요가 없는지를 판단하기 위해 존재
▪
비트가 1이면 보조기억장치에 저장된 페이지의 내용과 메모리에 저장된 페이지의 내용이 서로 다른 값을 갖게 되고, 이 페이지가 스왑 아웃 될 경우 변경된 값을 보조기억장치에 기록하는 작업이 추가됨
엔트리에는 이 밖에 더 많은 정보가 있고, 이것만 알아도 실제로 CPU가 메모리에 어떻게 접근하며 가상 메모리를 어떻게 다루는지 알 수 있음(
self-learning-cs의 page-table 항목 참고)
(펼치기 가능)
![](https://cdn.lazyrockets.com/_next/static/media/github-icon.f892685c.png)
▪
페이징의 이점
•
쓰기 시 복사(copy on write)
: 프로세스 간에 페이지를 공유하는 대표적인 사례
◦
부모 프로세스가 자식 프로세스를 만들 때 부모 프로세서의 메모리 영역이 다른 영역에 자식 프로세스로 복제되는데, 이는 생성 시간을 늦출 뿐만 아니라 불필요한 메모리 낭비를 야기함
◦
쓰기 시 복사에서는 자식 프로세스의 페이지 테이블에서 부모 프로세스의 프레임 번호를 가리키게 하고, 읽기 작업만 이어나가면 이 상태가 지속됨
◦
그러다가 부모 혹은 자식 프로세스 둘 중 하나가 페이지에 쓰기 작업을 하면 그 순간 해당 페이지가 별도의 공간으로 복제되고, 이것이 쓰기 시 복사임
◦
이를 통해 프로세스 생성 시간을 줄이는 것은 물론 메모리 공간 절약도 가능함
•
계측정 페이징(hierarchical paging = multilevel page table)
: 페이지 테이블을 페이징하여 여러 단계의 페이지를 두는 방법으로, 프로세스를 이루는 모든 페이지 테이블 엔트리를 항상 메모리에 유지하지 않을 수 있게 함
◦
페이지 테이블의 크기는 생각보다 작지 않고, 프로세스의 크기가 커지면 자연히 프로세스 테이블의 크기도 커지기 때문에 프로세스를 이루는 모든 페이지 테이블 엔트리를 메모리에 두는 것은 큰메모리 낭비임
◦
프로세스의 페이지 테이블을 여러 개의 페이지로 자르고, 바깥쪽에 페이지 테이블을 하나 더 두어 잘린 페이지 테이블의 페이지들을 가리키게 하는 방식
▪
이렇게 하고 페이지 테이블 중 일부는 보조기억장치에 보내고 필요할 때 메모리에 적재함
◦
계층적 페이징을 사용할 경우 CPU가 발생하는 논리 주소도 달라짐
▪
기존: <페이지 번호, 변위>
▪
이후: <바깥 페이지 번호, 안쪽 페이지 번호, 변위>
1.
바깥 페이지 번호를 통해 페이지 테이블의 페이지를 찾기
2.
페이지 테이블의 페이지를 통해 프레임 번호를 찾고 변위를 더함으로써 물리 주소 얻기
◦
페이지 테이블의 계층은 세 개, 네 개, 그 이상의 계층으로도 구성될 수 있지만 페이지 계층이늘어날수록 페이지 폴트가 발생했을 경우 메모리 참조 횟수가 많아짐