-
[WEEK11] 페이징은 왜 하는걸까 (Pintos PROJECT3 : VIRTUAL MEMORY)SW Jungle/TIL (Today I Learned) 2022. 12. 6. 10:59
운영체제의 Memory Management를 구현하면서, 페이징이라는 개념이 왜 쓰이는지 궁금해졌다.
이번 글에서는 페이징이란 무엇이고, 운영체제가 페이징을 왜 하는지에 대해 알아볼 예정이다.
페이징은 메모리를 관리하는 방법이다.
페이징의 기본 아이디어는, 물리 메모리 공간과 가상 메모리 공간을 일정 크기로 나누어 매핑시켜 운영체제가 관리의 주체가 됨으로써, 물리 메모리 공간이 연속적으로 할당되지 않아도 되게끔 만드는 것이다.
질문 1. 왜 가상 메모리 공간이라는 것이 필요한 걸까?
만약 물리 메모리에서 프로그램들을 돌린다고 가정해보자.
돌려야 하는 프로그램이 하나라면, 굳이 가상메모리가 필요하지 않을 수 있다. 어차피 혼자서 메모리 공간을 다 써도 되기 때문에, 프로그램이 주어진 공간을 자유롭게 활용하도록 해도 문제될 게 없다.
그런데 만약 프로그램을 여러개 돌려야 한다면 문제가 생긴다.
두 프로그램이 같은 메모리에서 돌아간다면 서로의 공간을 분리시켜 줘야 한다.
그렇지 않으면 서로 메모리를 참조하다가 같은 주소 공간을 참조하게 되고, 충돌이 일어나게 된다.
그럼 단순하게 생각해서, 물리 메모리 공간을 정확히 반으로 갈라서 하나는 얘, 다른 하나는 얘 주는 식으로 하면 될까?
물론 이론상 가능하기는 하겠다. 뭐 프로그램 두 개 까지는 큰 문제가 없을 수도 있다.
그러면 프로그램을 한 5개 돌린다고 가정해보자.
운영체제는 메모리 공간을 5등분해서 그들에게 주었다.
그런데 사용자가 1번 프로그램과 5번 프로그램을 가지고서는 별로 할 일이 없었는지, 먼저 종료시켰다.
그래서 메모리는 양 끝이 텅 비게 되었다.
위 그림의 각각의 공간이 1MB씩의 공간을 의미한다고 가정하겠다.
사용자는 새로운 응용 프로그램을 실행하고 싶은데, 그 프로그램은 1.5MB의 메모리 공간을 필요로 한다.
메모리에는 분명 2MB의 공간이 남아 있음에도 불구하고, 새로운 응용 프로그램은 연속적인 1.5MB의 공간을 가질 수 없다.
단편화 (fragmentation) 현상이 발생하는 것이다.
그래서 운영체제는 이런 현상이 발생하지 않도록 효율적으로 메모리를 관리해줘야 한다.
저 위의 그림을 다시 봤을 때, 1.5MB의 공간을 주는 방법을 생각해 보자.
윗쪽 empty 공간 1MB를 주고, 아랫쪽의 0.5MB를 주면 될 것 같지만, 프로그램은 연속된 공간을 받고 싶어한다.
그럼 연속된 공간인 척 속여서 가상의 주소를 주고, 프로그램이 참조하려고 할 때마다 운영체제가 알맞은 주소에 대신 기록해주는 건 어떨까?
이런 아이디어에서 시작된 것이 가상 메모리 (Virtual Memory)인 것이다.
실제 물리 메모리로의 접근은 오직 커널(운영체제)만이 하고, 유저 프로그램은 운영체제가 제공한 가상 메모리를 활용한다.
이런 속임수를 사용하면 각 프로그램은 마치 자기 혼자 컴퓨터의 모든 자원을 사용하는 듯한 착각을 할 수 있게 된다.
모든 획기적인 아이디어가 그렇듯, 세부적인 구현에는 많은 개념이 들어가는데 그 중 하나가 페이징 개념이다.
질문 2. 페이징이 뭔가요? 왜 필요한가요?
가상 메모리를 활용하면 유저 프로그램은 가상 주소를 활용하여 메모리에 접근하려 할 것이다.
만약 운영체제가 부여해준 가상 주소가 굉장히 파편화되어 있다면 어떨까?
극단적으로 생각해서, 매 바이트가 각각 다른 물리 주소에 매핑(mapping)되어 있다고 해보자.
그러면 운영체제는 각 가상주소와 물리주소를 매핑하는 정보를 모두 갖고 있어야 할 것이다. 예를 들어 1MB를 할당했다고 하면, 약 백만 개의 매핑 정보를 갖고 있어야 하는 것이다. 각 매핑 정보가 2바이트 (가상주소 1바이트, 물리주소 1바이트라고 가정하면) 씩만 차지한다고 해도, 매핑 정보를 보관하기 위해 운영체제는 2MB 의 공간을 사용해야 한다. 배보다 배꼽이 더 큰 상황이다.
이런 문제를 해결하기 위해, 일정 크기의 블록으로 메모리를 떼어주는 페이징이라는 개념을 도입하게 된다. Pintos에서는 4KB를 페이지 사이즈로 잡는데, 그러면 1MB는 256개 페이지로 나눠지게 된다. 아까처럼 각 매핑 정보가 2바이트만 차지한다고 가정하면, 이번에는 매핑 정보를 위해 512바이트 (0.5KB, 약 0.0005MB) 의 메모리 공간만 사용하면 된다. 차지하는 메모리 공간의 크기가 현저히 적어진 것을 확인할 수 있다.
이렇듯 페이징은, 가상 메모리와 물리 메모리를 운영체제가 효율적으로 관리하기 위해 도입한 개념이다.
기본적으로 가상 메모리와 물리 메모리를 특정 크기 (x64-86 linux에서는 4KB)의 블록으로 나눠서 다루게 된다.
기술이 발전하면서, 컴퓨터는 점점 더 많은 프로그램을 수많은 프로세스 위에서 돌려야 하게 되었다. 심지어 각 프로세스가 차지하는 메모리의 크기가 유동적일 수 있다. 메모리를 많이 먹기도 하다가, 적게 먹기도 한다.
한정적인 물리 메모리 상에서, 많은 프로그램이 효율적으로 동작할 수 있도록 하는 운영체제의 마법은 참 신비롭다. 마법이 다른게 아니라 바로 이런 아이디어와 알고리즘, 자료구조인 것 같다...
이 글에서 정리한 페이지와 가상 메모리에 대한 내용은 정말 빙산의 일각의 일각이다. 더 깊게 파보면 재밌는 내용이 많으니, 이 글을 보시는 여러분도 이것저것 찾아보기를 권한다.
참고문서 : Paging in Operating System
'SW Jungle > TIL (Today I Learned)' 카테고리의 다른 글
[WEEK13] Pintos에서의 FAT 구현 (Pintos PROJECT4 : FILE SYSTEM) (0) 2022.12.20 [WEEK12] Lazy Loading (Pintos PROJECT3 : VIRTUAL MEMORY) (0) 2022.12.13 [WEEK09~10] syscall wait()의 구현 - 구조 설계를 중점으로 (Pintos PROJECT2 : USER PROGRAMS) (0) 2022.11.29 [WEEK08] Pintos PROJECT1 : THREADS (0) 2022.11.17 [WEEK07] C언어에서 문자열 다루기. 근데 이제 포인터와 파싱(parsing)을 곁들인 (0) 2022.11.10