프로세스는 독자적인 메모리공간을 할당받아 사용합니다.
싱글프로세스 환경에서는 프로세스 하나만 돌아가기 때문에
컴퓨터의 리소스(메모리 등의 자원)을 독차지해도 괜찮았습니다.
이런 환경에서는 여러 동작을 수행할 때에는 쓰레드를 여러 개를 구현하여 동작하는데
각각의 쓰레드는 하나의 프로세스를 공유하다보니
각자의 동작에 영향을 줄 가능성이 있습니다.
쉽게 예로들어보면, 여러분의 카톡 데이터가 롤 게임하는데 영향을 줘서 q가 잘못나가는 식으로요.
현대의 컴퓨터는 이런 이슈를 해결하고자
멀티프로세스 환경으로 발전해나갔습니다.
이제 카톡/롤/유튜브 등등이 독립적인 프로세스로 실행할 수 있습니다.
이 결과, 안정성이 좋아졌지만, 각 프로세스마다 리소스를 어떻게 할당해야할지 고민해야합니다.
그 각각의 리소스를 할당하는 공간을
'가상메모리주소 공간(virtual memory address space)'이라고 부릅니다.
'가상'이라는 용어 때문에, '메모리를 만들어낸다'라고 오해하기도 했는데,
여기서 '가상'의 의미는 '프로세스가 혼자 프로그램을 동작하는 것처럼 만드는'걸 의미합니다.
메모리 공간을 독립적으로 할당해,
프로세스 하나 하나의 입장에서는
'나 혼자만 실행하고 있구나'라고 인지하는 거죠.
가상메모리를 어떻게 할당할지에 대해서 많은 방법이 있었는데
(시분할,정적 재배,segmentation...)
현대 컴퓨터 구조에서 주로사용하는 방법은 paging기법입니다.
paging은 프로세스의 가상주소공간을 page라는 일정한 공간으로 나눠서
실제메모리에 mapping하는 방식을 말합니다.
mapping을 할 때에는 page table이라는 자료구조를 거쳐
가상 주소공간은 프레임이라는 단위로 들어갑니다.
(리눅스 커널에서는 별다른 설정이 없으면 컴파일시 page당 4kb)
페이지 테이블을 바라보는 관점이
시스템과 하드웨어 각각이 다소 차이가 있습니다.
시스템적으로는 범용성을 위해서
ARM이든 AMD든 관계없이
다양한 아키텍쳐가 접근가능한 인터페이스를 만들어야합니다.
반면 하드웨어, 특히나 자율주행,스마트 디바이스에 사용되는
ARM 아키텍쳐관점으로보면
기기의 성능을 증가시키는 게 주요관심입니다.
이제 각각의 관점에 따라서 Page table을 어떻게 구성하는지 보겠습니다.
리눅스 커널에서는 MultiLevel page구조를 활용합니다.
왜 여러개의 구조로 나눈걸까요?
가상메모리-물리메모리를 1:1로 메핑한다면
복잡한 구조가 필요없을 수 있습니다.
하지만 우리가 사용하는 프로세스가 자주 쓰일수 있고
그렇지 않을 수도 있는데
만약 특정 프로세스의 메모리할당을 크게 해줘서 메모리낭비가 된다면 어떨까요?
또한 프로세스 주소를 찾는데 더 힘들지 않을까요?
여러분들이 대형병원에 들렀습니다.
먼저 데스크에 물어봅니다.
"제가 척추가 아픈데...어디로 가면 되나요??"
"네 정형외과고요,6층으로 가시면 됩니다"
그럼 6층으로 간 뒤에 6층 데스크에서
"지금 어디어디가 아픈데 어디로 가면 될까요?"
"접수하시고 000선생님 방 앞에 대기해주세요"
처음부터 1층 데스크에서
"제가 어디가 아픈데, 정형외과의 무슨 선생님을 찾으면 될까요?"
라고 안내하면 더 빠르지 않냐고요?
물론 데스크가 한가하고 여러분의 기억이 좋다면 가능하겠지만,
현실적으로는 힘듭니다.
데스크도 다른 여러 손님들을 봐야하고
기껏해서 알려줬더니 '6층왔는데...무슨 선생님을 찾아가더라...'라고 헷갈릴 수 있죠.
이처럼 메모리가 프로세스 주소를 찾아가기 편하면서
메모리공간을 효율적으로 쓰기위해
멀티레벨로 페이지를 나웠습니다.
(멀티레벨 페이지에 대한 설명입니다.)
아래 글은 실제 리눅스에서 어떤식으로 메모리가 저정되는지 정리한 글입니다.
링크에 들아가셔서 crash utility를 통해
어떤 식으로 가상주소-물리주소 메핑이 되었는지 확인하실 수 있습니다.
2023.10.23 - [CS지식 학습] - 캐시메모리는 무엇이고 어떻게 활용이 될까??
메모리 계층구조를 배우면서 캐시에 대한 내용, 기억하시나요?
cache에서 임시저장된 메모리 주소를 찾으면
메모리를 찾을 때의 시간을 더욱 단축할 수 있습니다.
TLB(Translate Lookasdie Buffer)도 이 캐시의 개념을 활용해서
Page table의 주소를 미리 저장하고 있습니다.
Page table은 ram에 저장이 되어있는데
CPU가 Ram에 접근하는 것보다
시간절약을 하게 만들어줍니다.
이를 저장하기 위해 ARM아키텍쳐에서는
TTBR이라는 레지스터를 사용합니다.
TTBR0은 유저공간에서의 프로세스를 저장하고
상위비트가 0으로 시작한다는 특징을 가지고 있습니다.
반면 TTBR1은 커널공간(운영체제 레벨)의 프로세스를 저장하고
상위비트가 1로 시작한다는 특징을 가지고 있습니다.
(그림에서 F로 시작하는데, 16진수이므로 2진수로 변환하면 1111)
TTBR레지스터에 가장주소공간을 임시저장했다가
물리주소로 빠르게 메핑합니다.
https://elixir.bootlin.com/linux/v5.14.21/source/Documentation/arm64/memory.rst
TTBR은 코드로고 확인할 수 있습니다.
커널 5.14버전에서
/Documentatuin/arm64/memory.rst파일에 있는 부분입니다.
프로그래머스 데브코스 리눅스 커널 전문가과정
(해당 글은 '권택준'수강생의 최종과제를 참고하여 제작하였습니다.
좋은 자료를 만들어주심에 감사합니다.)
GIC (0) | 2024.04.18 |
---|---|
스택카나리(Stack canary) (0) | 2024.04.10 |
시스템 콜의 ftrace 분석을 해보자! (0) | 2024.04.02 |
익셉션(Exception) (0) | 2024.03.15 |
인터럽트 (1) | 2024.03.13 |
댓글 영역