가상 메모리
메모리는 컴퓨터 자원에 있어서 중요한 역할을 하는 H/W입니다. 프로세스가 동작하기 위해서는 메모리에 데이터를 올리고 CPU가 메모리에 접근하여 연산을 하는 방식이므로 메모리의 크기와 성능은 컴퓨팅의 성능과 아주 밀접한 관계가 있습니다.
과거 컴퓨터의 주소 버스(CPU가 메모리나 입출력 장치에 직접적으로 주소를 보낼 때 사용되는 데이터 버스)의 크기가 32비트였기 때문에 메모리의 크기는 4GB로 한정적일 수 밖에 없었습니다.
※ 메모리의 단위는 1byte. 즉 주소한칸에 1byte의 데이터가 저장됨. (ex : 0x00000001 => 0001 0001 데이터 저장)
그러므로 표현할 수 있는 주소가 2^32 주소범위라면 주소마다 1바이트이므로 4GB의 메모리 크기가 최대로 표현될 수 있음.(1KB = 2^10*1byte, 1MB = 2^20*1byte, 1GB = 2^30*1byte)
하지만 저희는 프로그램들을 4GB에 맞게 구동시키지 않죠? 물론 64비트 아키텍처가 만들어지면서 메모리의 크기 한계는 극복이 되었지만 이전에는 더 효율적인 메모리와 여러개의 프로세스를 사용하기 위해 가상 주소라는 개념을 만들어 사용했습니다.
프로세스가 컴파일, 링크 그리고 로드 과정을 거치면서 사용되는 각 영역의 주소는 실제 메모리 주소와 매핑되는 주소가 아닌 가상 주소입니다. 가상 주소가 만들어지는 과정은 다음과 같습니다.
- 컴파일 타임 : compiler가 symbol table을 만들고 주소는 symbol table relative한 주소로 이루어진다. 이때 compile된 .o 파일은 주소 0부터 시작한다.
- 링크 타임 : .o파일들과 system에서 제공하는 library들을 묶어서 symbol table에 의존적이지 않은 주소를 만들어 낸다. 결과로 만들어진 실행파일 또한 주소는 0부터 시작한다.
- 로드 타임 : 프로그램 실행을 위해 loader는 데이터영역과 코드 영역등 중요 페이지를 메모리에 올린다.
- 실행 타임 : 프로세스가 실행 될 때 물리 주소가 바뀌는 경우, 주소 결정은 MMU와 같은 H/W가 사용된다.
이후 CPU는 실행중 PC(Program Counter)에 저장된 필요한 명령어의 상대주소를 통해 MMU가 물리 주소로 번역후 메모리에 접근하게 됩니다. 이와 관련된 내용은 아래에 상세히 나옵니다.
페이징
페이징이란 주소 공간을 동일한 크기의 page로 나누어 관리하는 것을 의미합니다. 위에서 본 프로세스의 가상 메모리를 4KB로 나누어 하나의 Block를 의미하는 것입니다. 물리 메모리에서는 frame이라는 용어를 사용합니다. 페이지가 하나의 frame을 할당 받으면 그 페이지는 물리메모리에 위치하게 되는 것이죠. 할당받지 못한 페이지들은 ssd와 같은 저장장치에 저장되어 있습니다. 이와 같이 관리하는 이유는 데이터를 사용할때 보통 연속된 주소의 데이터를 사용하는 경우가 많기 때문에 일정한 단위로 데이터를 묶어 관리하는 것이 훨씬 용이하기 때문입니다. 예를 들어 프로세스 작동에 필요한 여러 데이터를 각 사용할때마다 ssd와 같은 저장장치에 접근해서 달라하면 오버헤드가 엄청 날 것입니다.
cpu가 바라보는 주소는 두 부분으로 나뉘는데 바로 page 번호와 page 주소입니다
page 번호 | page 주소 |
프로세스가 가진 페이지의 고유한 주소 | 페이지의 내부 주소 |
Page 주소는 offset이라고도 부르는데 이는 페이지의 크기가 4KB이기 때문에 페이지 안에서의 내부 주소를 가르키기 위한 주소비트입니다. 따라서 상위비트인 page 번호를 통해서 페이지를 찾고 하위 비트인 page 주소를 통해 페이지 내부에서의 정확한 주소를 알수 있는 것입니다.
● 페이지 테이블
- 각 프로세스의 페이지 정보를 저장하는 테이블. 프로세스마다 하나의 페이지 테이블을 가지게 된다.
페이지 테이블 내부는 위에서 말한 page 번호와 그에 맞는 frame의 시작 주소를 매핑시켜 저장해놓습니다. 이러면 페이지 테이블을 보고 page번호(20bit)를 실제 물리 메모리 주소로 번역해 page 주소(12비트)와 결합하여 원하는 데이터가 있는 물리 메모리 주소를 찾을 수 있습니다. 페이지 테이블은 실제 물리 메모리에 올라가 있는데 이를 위해 PTBR(Page Table Base Register)을 통해 페이지 테이블의 시작 주소를 저장하고 페이지 테이블에 접근하여 사용합니다.
● 페이지 테이블 엔트리
-page table의 record
위에서 잠깐 언급한거와 같이 페이지 테이블 내부는 page와 번호와 매핑되는 frame의 시작 주소를 저장합니다. 앞서 page 번호가 20비트이기 때문에 나머지 12비트는 flag 비트로 사용됩니다. flag 비트는 다음과 같습니다.
- Accessed Bit(페이지 접근 여부)
- Dirty Bit(페이지 변경 여부)
- Present Bit(현재 페이지에 할당된 frame이 있는지)
- Read/Write Bit(읽기와 쓰기 권한)
학부 운영체제 마지막 과제가 cow(copy on write)를 구현하는 것이었는데 이때 flag 비트가 정말 정말 중요한 역할을 하는 것을 알 수 있었습니다. 별로 안중요한거 같았는데 운영체제 구현에 있어 필수적인 요소임을 알게 되었습니다.(필요하지 않은 것은 사실 없겠죠ㅎ)
페이지 테이블을 통해 실제 물리 메모리 주소로 번역되는 과정은 다음과 같습니다.
- 프로세스의 페이지 테이블 시작주소가 PTBR에 저장된다.
- cpu는 가상주소를 MMU로 보내 물리주소로 번역을 요청한다.
- MMU는 페이지 테이블의 시작주소로 가서 가상주소의 상위 20비트(페이지 번호)를 통해 해당 인덱스로 가 frame 번호를 알아온다.
(페이지 번호와 페이지 테이블 시작 주소에서 상대적으로 얼마나 떨어졌나를 통해서 인덱스가 되는거 같습니다.) - frame번호와 page 주소를 통해 물리 주소를 만든다.
TLB(Translation Look-aside Buffer)
위와 같은 방식으로 번역이 되면 항상 메모리에 올라가 있는 페이지 테이블로 접근 후, 실제 데이터가 있는 물리 메모리 주소로 접근 해야합니다. 사실 cpu입장에서 메모리는 bottle neck이 되기에 엄청 답답하겠죠? 그래서 이를 해결하기 위해 사용된것이 TLB입니다. TLB는 레지스터이기에 훨씬 빠르게 동작하고 MMU안에 이를 배치해서 캐시하는 역할을 수행합니다. page table을 이용해 변환된 주소를 저장하여 만약 저장되어 있는 page 번호가 다시 번역이 요청된다면 TLB에서 빠르게 수행하여 값을 전달합니다. 그렇다면 자주 사용하는 page 번호를 저장하는 것이 중요하겠죠?? Hit 비율이 굉장히 중요하기 때문에 이를 고려해 잘 저장한다면 확실한 성능 개선이 이루어질 수 있습니다.
Multilevel Page Table
앞서 페이지 번호의 크기는 20bit라고 여러번 언급이 되었습니다. 그렇다면 페이지 테이블의 크기를 계산해 보았을때 최대 페이지 테이블크기는 2^20*4B = 4MB가 됩니다.(page table entry는 보통 4B크기를 차지합니다.) 만약 100개의 프로세스를 작동시킨다면 400MB만큼 페이지 테이블을 위한 공간이 필요한것입니다.
이를 위해 Multi-level page table이 생겼습니다. 이는 page table을 하나 더 두어, page table을 가르키게 하는 것입니다. 즉, page table을 위한 page table을 만드는것입니다. 프로세승에 모든 페이지 테이블을 메모리에 올려두는것이 아니라 필요한 페이지에 대한 테이블만 메모리에 올려 메모리 사용량을 줄일 수 있게 됩니다. 단점은 그만큼 여러 페이지 테이블에 접근해야 하기 때문에 오버헤드가 증가할 수 있어 TLB의 hit radio가 중요하겠죠?
Inverted Page Table
이 또한 물리 메모리 용량의 한계를 극복하고자 나온 방식입니다. Inverted Page Table 기법은 cpu에서 참조하는 address와 PID 조합으로 Page ID를 만들어 Page Table 내에서 Page ID를 검색합니다. 그후 발견이 된다면, 해당 Frame을 Logical address 공간으로 mapping합니다.
이렇게 글만 봐서는 잘이해가 가지 않으실 텐데 요약하면 시스템 전체에서 하나의 페이지 테이블만 두고 페이지 테이블의 인덱스는 frame의 번호가 되고 엔트리 값은 PID와 가상 주소가 됩니다. 그리고 요청이 오면 테이블에서 일치하는 프로세스와 그 가상주소를 찾아 인덱스인 frame에 매핑하게 됩니다.
이렇게 페이지 테이블을 하나만 두고 사용한다면 페이지 테이블을 위한 메모리의 용량은 메모리 프레임수 만큼만 사용하면 될것입니다. 만약 메모리가 4GB의 32비트 주소 공간이라면 2^20 1MB만 페이지 테이블을 위한 공간으로 사용하게 됩니다.(엔트리의 용량이 1B일때) 이렇게 두가지 방식으로 메모리의 용량 증가 문제를 해결할 수 있습니다.
Demand Paging
demand paging이란 procces의 실행을 위한 모든 page를 메모리에 올리지 않고, 필요한 page의 요청이 발생할 때 메모리에 올리는 paging 기법입니다.
장점 | 단점 |
-실행을 위한 물리 메모리 구성 시간이 줄어든다. -프로세스의 전체 이미지를 메모리에 올리지 않기 때문에 실제 필요한 전체 물리 메모리의 양을 줄일 수 있다. |
-만약 참조하려는 page가 메모리에 없을 경우 sendary storage에 대한 접근이 필요하다.(page fault) |
'CS' 카테고리의 다른 글
mac m1 환경에서 xv6 빌드하기(UTM, EC2) (2) | 2023.09.24 |
---|