[sw정글 11주차] 세상에서 가장 자세한 pintos 메모리구조 (그림으로 이해하는 OS 메모리 구조)

Date:     Updated:

카테고리:

태그:

🤒소잃고 외양간 고치기

낙엽도 지는 모습이 보이고, 월드컵도 지나가고, 날씨도 추워진다. 협력사로 네이버에서 방문한 이후에는 뭔가 더 어수선한 분위기인것 같다. 이럴 때 일수록 몸과 마음을 다잡고 꾸준히 해나가야지! 라고 생각하자마자 몸살감기에 걸렸다. 코로나도, 독감도 모두 음성판정 났다. 그래도 머리가 너무 어지러워서 결국 3일정도는 잠만잤다.

outside

긴 잠에서 깨어나서 얻은 것이 있다. 상쾌한 공기를 깊게 들어마셨을 때, 생각보다 기분좋은 쾌감을 얻을 수 있다는 것이다. 뭔가에 집중할 때, 나도모르게 호흡이 “매우” 얕아지는 것 같다. 환기를 시키고, 공기를 폐 끝까지 들여마셨을 때의 그 상쾌함을 자주 느끼는것이 참 중요한 것 같다. 건강과도 직결되지만, 머리도 맑아지며 뭔가… 더 객관적으로 볼 수 있는 느낌? 이 드는 것 같다. 현재 나의 상황도 객관적으로 보이고, 나의 몸 상태, 나의 코드 상태, 오늘 해야할 일들 등 많은 것들에 대해 객관성을 얻게되는 것 같다. 무언가를 “직시” 한다는것은 매우어렵다. 이 때, 한번 들여쉬는 공기가 좀 더 객관적인 관점으로 몸과 마음을 리셋해주는 것 같다.

🚀시작

VM구조에 대해서 여러가지로 이해가 가지 않았었다. 그 이유는 OS마다 메모리 사용 방법이 달라서이다. 이게 정말 핵심이다. 구글링을 하면서 리눅스 관련 자료를 많이 찾아들 보지만, 핀토스와는 조금 다르다. 구글링을 하면서 핀토스 관련 자료를 많이 찾아들 보지만, 64bit 에서는 조금 다르다. PINTOS 프로그램 자체가 옛날(2004년)에 만들어져서 인지, 32비트로 해당 내용을 설명하는 자료들도 많이 있다.

X86-64, 핀토스 운영체제용 자료가 별로 없다 보니 VM구조를 이해하는데에 더욱 어려움이 있었던 것 같다. 한번 해당 내용에 대하여, 뻔한 이야기부터 시작해 보도록 하겠다. 평소 필자는 “구글링하면 맨위에 바로 나올법한 뻔한 내용”을 쓰는것을 별로 좋아하지 않았다. 쓰는사람 읽는사람 모두 이득이 적다고 생각했기 때문이다. 하지만… 핀토스 4주차인 지금도, 반 구성원들이 이해하고 있는 VM의 모습이 조금씩 다름을 느꼈다. 따라서, 이번 글에서는 뻔한 내용부터 consensus를 맞추어 나가며 글을 전개해 나가도록 하겠다. 사실 아파서 공부를 많이 못했다.(별로 쓸 내용이 없다 ㅠㅠ)

😢뻔한내용 1

첫번째 뻔한 내용은 다음과 같다.

유저영역은 여러개다

처음에는 유저를 속인다는 말이 이해가 잘 되지 않았었다. '컴퓨터가 뭘 속여? ㅋㅋ'라고 생각하기도 했으나 이보다 잘 표현한 말이 없는 것 같다. 어떤 추상화에 대해 이런 말을 하는걸까? 실행중인 프로그램의 갯수(정확히는 프로세스의 개수)만큼 유저영역이 있는 것이다. 크롬, , 카카오톡을 실행시키면, 각각의 프로그램들은 마치 자신이 메모리를 전부 사용하는 것 처럼 느낄 수 있도록 만들어준다는 뜻이다.

chrome lol kakao

그리고 속임당하고 있는 유저들(프로그램들)은 이렇게 생각하고 있는 것이다. chrome lol kakao2

하지만 뻔한 이야기이겠지만, 사실 구라고 여러개의 유저영역이 존재한다. 그리고 보기 편하라고 많은 자료들은 그냥 하나로 퉁쳐서 그린다.

chrome lol kakao3

😢뻔한내용 2

두번째 내용은, CPU작동원리이다. 처음에는 CPU를 속인다는 말이 이해가 잘 되지 않았다. '컴퓨터가 뭘 속아? ㅋㅋ'라고 생각하기도 했으나 이보다 잘 표현한 말이 없는 것 같다. 어떤 추상화에 대해 이런 말을 하는걸까? CPU는 상상력이 풍부한 방구석 찐따라고 생각하면 편하다.

CPU

64비트의 경우, 주소표현을 위해 48비트를 사용한다. 248 = 240+8이니까, “1000”이 4번 곱해지고, 뒤의 8승은 256이므로, 256테라바이트가 되는 것이다. (1:킬로 2:메가 3:기가 4:테라)

마치 CPU가 256TB에 대해 전지전능한 권한이 있는것 처럼 속이는 것이다.

CPU2

그리고 속아넘어간 CPU가 꿈에서 깨지 않도록… 우리가 만들 VM시스템은 이를 이해하고 모두 가져다 주어야 하는 것이다.

CPU3

CPU에 대한 비유를 마치고 다음 뻔한 이야기를 해보도록 하겠다.

😢뻔한내용 3

세번째 뻔한 내용은 다음과 같다.

가상메모리는 ‘가상’ 메모리이다.

CPU는 마치 누르면 모든것을 이루어 주는 마법의 가상주소록을 보고 있다. (MMU에다가 대고)주소를 외치면 마치 마법처럼 뿅! 값이 나온다. 하지만 가상 공간을 정말로 CPU의 뇌내망상인 것이다. 실제로는 아무런 값도 존재하지 않는다. 정말 뇌내망상인 것이다.

virtual adress

위와 같은 그림을 본적이 있을 것이다. 하지만 이러한 형태의 그림들이 오히려 오해를 가중시키는 역할을 한다고 볼수도 있다. 오해를 풀 수 있도록, 다음과 같은 그림을 여러분께 제안한다.

virtual adress2

그렇다. virtual address space라는 공간 속에는 그 어떤것도 존재하지 않는 것이다.

CPU4

빵빵한 주소공간을 사용한다고 생각한 CPU이다. 하지만 실제 이는 ‘가상’메모리 공간이므로 아무것도 존재하지 않는다. 실제로는 이와 연결된 곳(실제 물리메모리)를 어렵사리 찾아가야 그 값을 얻을 수 있는 것이다. va, kva, 유저공간, 커널공간 모두 포함이다. 이들 모두 가상공간이다.

커널공간은 가상공간 아닌데요??

=> 아니다. 물리메모리와 1:1 맵핑된 커널공간도 가상공간이다. 메모리와 동일한 모양을 만들어 둔 것 뿐이다. 이 주소에도 아무것도 없다. 비록 1:1맵핑되어있어서 금방 가져오겠지만 무튼 실제로는 아무것도 존재하지 않는 것이다. 유저영역, 커널영역 할것 없이 앞으로는 위의 그림처럼 좀더 얇실한 가상공간으로 떠올리면 오해가 줄지 않을까 싶다.


🤩가상공간의 모양

글을 본격적으로 써보겠다.

🚀큰그림

그렇다면 이제 가상공간이 어떻게 생겼는지 그 모양을 보도록 하겠다. 일단 아주 멀리서 바라보도록 하겠다.

VM bigpicture

48비트로 표현할 수 있는 아주 거대한 영역의 아주 일부분을 우리가 사용하는 것이다. (실제 사용하는 부분은 그림에 표기된 것 보다 조금 더 작게 표현되는게 비율상 맞다) 그렇다면 이를 조금 더 확대 해 보도록 하겠다.

VM middlepicture

그렇다면 이처럼 kernbase를 기준으로 명확하게 1:1 대응이 되는 것을 볼 수 있다. 커널베이스와 유저스택 사이에 큰 공간이 존재하는데 이는, 의미없는 빈공간이다. 이 빈공간도 “…“처리를 하도록 하겠다.

그렇다면 이는 위그림처럼, 유저스택 밑으로는 핀토스에서는 va라고 불리우는 영역이 된다. 그리고 리눅스에서는 여기를 유저영역이라고 한다. 마찬가지로 핀토스의 kva영역은 리눅스의 커널영역에 대응되는 것이다. 핀토스의 세부 값들에 대해 알아보도록 하겠다.

🚀작은그림

💾핀토스의 크기

그렇다면 어떻게 핀토스의 크기를 알 수 있을까?

init mem

오늘도 여김없이 등장하는 init.c이다. 여기서 크기를 결정해준다. 88번줄 paging_init에서 그 크기대로 메모리를 제한해 주고, 그 크기는 86번줄 에서 mem_end라는 이름으로 크기가 결정난다. 그렇다면 mem_end가 어떻게 찍히는지 palloc_init() 함수를 조금 더 자세히 보도록 하겠다.

paging_init

그렇다. 이처럼 명령어로 들어온 값이 여기까지 흘러들어온다. 우리의 옵션대로 20MiB를 메모리크기로 설정해 준 모습이다. (ext_mem(= 0X13e0000)이 우리가 알고자 했던 mem_end값이다.) 이는 핀토스 시스템의 전체 크기이다. paging_init()함수의 인자로 전달이 된다.

💾커널풀과 유저풀

위에서 핀토스의 크기를 결정해 주었다. 그리고 그 크기대로 메모리를 설정해 주었다. 메모리를 설정해 주는 부분(=paging_init) 마지막을 보면 populate_pools라는 부분이 있다. 이 부분이 바로 kva영역을 두동강내며 커널풀과 유저풀을 분리해주는 곳이다.

paging_init populate

paging_init()함수 내부의 populate_pools()내부에는, 커널영역인지 유저영역인지에 따라 init_pool()함수를 수행한다. 이 때의 출력 결과값을 보면 아래와 같다.

커널풀: start: 0X8004000000, end: 0X8004a21000 
유저풀: start: 0X8004a21000, end: 0X80053e0000 

그렇다 계산해보면 딱 절반이다. 이부분만 그림으로 나타내면 아래와 같다. 그리고 풀의합은 0X13e0000로써 약 20MiB가 된다. 따라서 아래처럼 정확히 1:1로 나뉘어진 kva영역을 그릴 수 있다.

kernpool userpool

💾할당

핀토스에서는 memory mapped영역도 없고, 힙도 없다. 그렇다면 어디에 할당될까? 정답은 kva영역의 커널풀에 할당이 된다. (유저 옵션을 주면 유저풀에 할당된다 (실험결과 참조))

malloc-palloc

리눅스에서는 어떻게 이루어질까? 궁금하신분은 아래를 클릭하여 보면 좋은 추가공부가 될 것이다.(열심히 썼음)

리눅스에서의 할당(핀토스와는 다름)

일단 malloc()과 mmap()은 어떤 차이점이 있을까? malloc()은 힙영역에, mmap()은 memory_mapped영역(힙과 스택 사이)에 할당된다. 또 추가적인 차이점을 들자면, mmap은 정적으로(하드코딩)할당하는데, malloc은 동적할당이 가능하기도 하다.

image

하지만 리눅스에서의 유저가 사용하는 malloc()은 mmap()과 동등한 개념이 아니다. 더 상위개념이다.

image

malloc()은 mmap()과 sbrk()를 포함하는 개념이다. 여기서 sbrk()는 space_break이다. 실제로 함수를 사용해보면, brk시리즈로 사용하면 힙영역이 늘어나고, mmap 시리즈를 사용하면 memory mapping segment영역이 늘어남을 알 수 있다.

image

(핀토스와 구조가 달라 혼란을 줄 수 있는)위 그림은 리눅스의 유저영역을 나타낸 그림이다. program_break_brk를 그 포인터로써 이용한다. malloc()을 통한 할당이 일어날 때 마다, 해당 포인터가 올라가면서 그 영역이 늘어난다. 즉 malloc()해줄 때 마다 heap영역이 늘어난다. 반대로 mmap()을 해주면 memory_mapped영역이 밑으로 내려온다.

참고로, 핀토스는 va와 kva영역으로 나뉘어져 있다. 그리고 리눅스는 (32bit기준)유저영역 커널영역으로 나뉘어져 있다.(그 차이점은 글하단부 참조참조)

💾유저영역

유저영역은 그렇다면 어떻게 찍힐까? 깃북 자료에 적절한 그림이 있었다.

gitbook va

위의 그림처럼 아래 0부터 0x400000 까지 빈 공간을 두고 시작한다. 일단 핀토스의 유저영역은 리눅스와는 다르다. memory mapped 영역이 존재하지 않는다. 힙영역도 존재하지 않는다. 실 값들을 찍어보면 예상과 비슷하게 맵핑된다.

va region

유저영역을 차지하는 위의 녀석들은… 이미 elf파일에서 어떻게 로드될지 정의되어있다. 아래와 같은 방법으로 elf파일을 찍어보면 된다.

readelf -Wl <파일이름>

image

그렇다. 컴파일완료된 시점에는 이미 va영역이 어떻게 셋팅될지 정해져 있다. elf파일은 알고있다.

🚀총합

그렇다 모든걸 정리하면 다음 그림과 같다.

⭐️⭐️⭐️⭐️⭐️ pintos-ultimate1

번외 이미지

pintos-ultimate2

그리고 잊지 말자 “가상”주소 공간에는 데이터가 없다. “진짜”는 물리에 있다.

pintos-ultimate

리눅스에서는, 유저영역과 커널영역으로 나뉜다. 핀토스에서는 va영역과 kva영역으로 나뉜다. kva영역 자체가 물리메모리와 1:1으로 대응되기 때문에…

va영역에 있는 모든 녀석들은 kva영역에도 존재한다. kva영역은 va의 데이터를 나타낸다.

하지만 리눅스에서 (32bit기준) 3:1로 나누어둔 유저영역과 커널영역은 조금 다르다. 유저영역의 값은 바로 물리에 맵핑될수도 있다. 즉…

유저영역에 있는 녀석은 커널영역에 없다. 다른데이터를 나타낸다.

linux

(위 그림은 page_table참조과정 생략)

이처럼 웹에 돌아다니는 리눅스개념과 핀토스개념이 혼재되었기 때문에 머릿속에 큰그림이 그려지지 않아 이해가 많이 어려웠던 것 같다. 내가 그린 그림을 통해, 다른 분들이 조금 더 쉽게 pintos프로젝트를 이해하면 좋겠다.

🚀금주 발표영상

🚀마치며…

이제 일주일 뒤면 나만의무기 프로젝트가 시작된다. 마지막 프로젝트를 하면 벌써 집에 갈 시간이다. 공부가 어려워도, 끝이 보여도, 감기에 걸려도, 16강에 진출해도, 창밖에 눈이와도, 뭔가 아쉬워도, 자만감이 들어도, 미래가 불안해도 이루어질 일은 이루어진다. pintos를 끝까지 마치고, 친구들과 마지막 프로젝트를 하고 집에가게 될 것이다. 정해진 미래이다. 중요한 건 꺾이지 않는 마음이다.

important thing



😵배우면서 깨달은 내용을 정리해 보았습니다. 틀린 것 같은 개념을 아래 댓글에 달아주시면 감사합니다😵

🌜 Thank you for reading it. Please leave your comments below😄

맨 위로 이동하기

swjungle survive 카테고리 내 다른 글 보러가기

댓글 남기기