ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • PintOS's Memory Structor
    SW Jungle/TIL 2024. 5. 21. 19:58

    이번글에서는 핀토스 VM 프로젝트를 진행하며 공부하게된 페이징 기법과 핀토스의 메모리 구조에 대해 글을 써보려고한다.

     

    더보기

    목차

    1. 프레임 과 페이지
    2. 페이징
    3. 핀토스에서의 주소 변환
    4. 핀토스의 메모리 구조

    프레임과 페이지

    프레임(frame): 물리 메모리를 일정한 크기로 나눈 블록이다.

     

    <프레임>
    페이지(page): 가상 메모리를 일정한 크기로 나눈 블록이다.

    <페이지>

     

    프레임과 페이지의 크기는 동일한 크기를 가지며 이 일정한 크기는 페이지 크기이다.

    일정한 크기 == 페이지 크기(사이즈) == 2^12 == 4096

     

     

    주소 하나당 1byte의 크기를 저장 할 수 있다. 따라서, 4096개의 주소 * 1byte = 4kB 이므로, 페이지 하나는 4kB의 크기를 가진다.

     

    페이지나 프레임이나 4096개의 연속된 행이 있는 리스트 라고 보았을 때 4096개의 인덱스를 가지고 원하는 행을 찾아갈 수 있다. 이 인덱스를 offset이라고 생각하면 된다. 그래서 64비트 주소에서 하위 12비트로 물리 오프셋을 가지는 것이다.

     

     

    이제 메모리 할당을 받을 때 4kB단위로 받을 것이다. 그래서 페이지 테이블 역시 4kB로 할당 받을 것이다. 64비트 주소 하나는 (ex. 0x0000800040001000) 는 8byte 이므로 페이지 테이블 안에 512개의 64비트 주소를 담을 수 있다. 512는 2^9 이라서 페이지 테이블들의 오프셋은 9비트를 가지는 것이다.

     

    우리가 하고 싶은것은
    가상주소로 물리주소를 찾아가는 것.

     

    페이지와 프레임은 동일한 사이즈이고 동일한 행을 가진다. va 하나로 pa하나를 찾아가야 한다. 우리는 페이지 테이블을 사용하기 때문에 페이지로 프레임을 찾아가야한다. 페이지는 어차피 4kB 단위로 관리되기 때문에 이 페이지 단위로만 페이지를 관리하면된다. 이 뜻이 무엇이냐하면 각각의 가상주소가 어디로 연결될지 페이지가 알필요 없다는 것이다. 해당 va가 어느 페이지에 속하는지만 알면 프레임을 찾고 거기서 오프셋 값만큼만 올라가면되기 때문이다.

     

     

    그래서 우리의 핀토스 페이지 구조체의 va 값에는 페이지 단위의 값만 담길 것이다.

    0x0000000000000001 값은 그냥 0x0000000000000000 va 값을 가지는 페이지 구조체를 찾아가면 자기가 속한 프레임을 찾아갈 수 있다.

     

     

    그래서 우리가 보조 테이블에서 va 값으로 페이지를 찾을때도 내가(요청하는 va가) 속한 테이블을 찾아야하므로 (키값이 페이지 단위이므로) pg_round_down(va)로 4kB 단위로 내림하여 찾는 것이다.

     

    핀토스의 메모리 구조

    pintos-kaist 64비트 의 메모리 구조이다.

     

    가상주소 체계에서 KERN_BASE를 기준으로 위쪽으로는 kva space, 아래로는 va space로 나뉜다. kva에는 pool이라는 영역이 있는데 이 영역은 물리 메모리와 1ㄷ1 매핑이된다. 핀토스에서 메모리를 할당 받을 때는 단 하나의 함수로 모두 할당 받고 있다는 것을 알고 있는가? 바로, palloc_get_page()로 할당 받는다. malloc() 역시 내부를 들어가보면 palloc을 부른다.(커널풀에 할당 받는데 후술 하겠다.)

     

    Pool

    이 pool이라는 영역은 핀토스가 사용하는 물리메모리를 추상화한 영역이라고 생각해도 된다.

    이 pool의 크기는 처음 부팅할 때 결정된다. 

    핀토스 실행할때 -m 20 으로 옵션을 주면 20메가바이트의 메모리를 가지라고 하는 것이고 실제 부팅 메시지도 그렇게 뜬다.

    궁금하다면 init.c의 palloc_init() 함수를 찾아보자!

     

    user pool 은 유저 프로그램이 사용하는 실제 데이터가 담긴 프레임 이 담긴다.

    kern_pool 에는 핀토스라는 운영체제가 사용하는 모든 것들이 담긴다. struct thread, struct page, struct frame, pml4 등등 

    malloc을 사용해도 kern_pool에 할당 받는데 여기서 사용하는 malloc은 커널이 사용할 것들을 할당 받기위해 사용되기 때문이고 유저가 호출해 힙영역에 할당받는 malloc은 우리 핀토스에는 없다. 필요하다면 시스템콜로 malloc을 구현하면 될 것이다.

    what? 프레임은 user pool 에 담긴다면서 왜 kern_pool 에 struct frame 이 할당되나요??? 프레임과 프레임 구조체는 다르다. 유저 풀에 있는 프레임은 정말 4kB의 프레임 그자체이고 (사실 페이지 단위로 주소하나 딸랑 주는거긴하지만 논리적으로 4kB씩 주는 것이 되니...) 프레임 구조체는 해당 프레임을 찾아가는용(표현한것) 이라고 나는 생각한다.

     

    핀토스에서의 주소 변환

    그래서 핀토스에서는 가상주소와 물리주소의 변환이 어떻게 되는가? vaddr.h를 보자.

     

    단순히 KERN_BASE를 더하고 빼서 변환한다. 이게 가능한 이유는 앞서 보여준 핀토스의 메모리 구조때문이다. kva영역의 pool 영역이 핀토스의 물리메모리를 추상화한 영역이기 때문이다.

     

    그래서 단순히 덧셈 뺄셈으로 물리 주소로 변환이 되는 것이다.

    그래서 이것들이 어디서 사용되냐???

    mmu.c 에서 사용되고 있다. 우리가 흔히 아는 pml4 페이지테이블로 오프셋으로 찾아가며 프레임과 조합하여 사용되고 있었다.

     

    번외

    번외로 그래서 유저 모드가 이 kva 영역에 접근하려하면 잘못된 접근으로 처리하는 것이다. 직접 바로 물리메모리에 접근하려 하는 것과 똑같기 때문이다.

     

    참고로 리눅스에서도 유저/커널 영역으로 가상주소를 나눈다고 한다. 각각의 프로세스들이 독자적인 페이지들을 가져 다른 프레임들을 가르키고 있어도 커널 가상 주소들은 동일한 (os가 담긴) 프레임들을 가르키고 있기 때문이다. (그래야 시스템 콜 과 같은 공통된 기능을 사용하니깐) 그래서 커널 주소로 접근하는 것은 엄격한 처리를 위해 영역을 나눈다고 한다.

     

    마치며,

    핀토스와 실제 이론 공부한것의 다른 점 때문에 좀 파악하기도 힘들었었다. 단순히 교육용이니깐~ 이렇게 구현한건가? 하고 이해 없이 넘어가기엔 그런 의도로 핀토스를 만들었을리도 없다고 생각해서 글을 작성하게 되었다.

     

    중요한 것은 페이지 단위로 데이터와 주소를 묶음으로 관리하고 찾아 간다는것. 그래서 적은 용량으로 그 많은 용량을 찾아갈  수 있다는 것이라고 느꼈다.

     

     

    'SW Jungle > TIL' 카테고리의 다른 글

    PintOS Project 3 VM swap in/out  (1) 2024.05.28
    pintos fork  (0) 2024.05.14
    malloc lab binary 케이스 메모리 이용률 개선하기  (1) 2024.04.18
    변수에 대한 이해  (0) 2024.04.12
    week01  (0) 2024.03.24
Designed by Tistory.