OS - 메모리 관리 기초
메모리 페이지의 상태
페이지의 상태는 Reserve/Commit/Free가 있음.
Commit상태는 하드랑 RAM모두 포함한다. 힙 메모리를 할당받으면 해당 메모리 페이지가 Commit 상태가 되는 것.
처음에는 Free상태였다가 할당받으면 Commit 문제없지?
그러면 Reserve는 왜 필요할까? 그냥 나중에 할지도 모르니까 예약해두는거임.
이러면 다른 요청에 의해서 reserve된 페이지는 할당에서 제외시킴
.
페이지 할당
가상 메모리 시스템은 페이지 관리로 관리되기 때문에 페이지 중간부터 할당을 시작할 수 없고, 페이지 크기의 배수 단위 할당만 가능함.
그러면 메모리 할당 시작 주소는? 페이지 크기일까?
=> 아님, 그러면 메모리 파편화가 심해질 수 있음 그래서 더 넓은 값을 할당의 경계로 삼는다. 그리고 이 때 쓰는 메모리 할당의 시작 주소가 될 수 있는 기본 단위를 "Allocation Granularity Boundary"라고 한다.
*페이지의 총 개수 = 가상메모리의 크기/ 페이지 하나당 크기
.
힙컨트롤
기본적으로 프로세스에 할당되는 힙을 디폴트힙, 프로세스힙이라고 함.
List에 capacity 지정해주듯, 프로세스에도 디폴트 힙 크기를 지정해줄 수 있음.
.
다이나믹 힙
디폴트 힙 이외에 시스템 함수 호출을 통해 힙을 생성할 수 있음. 이걸 다이나믹 힙이라 부름.
A기능 B기능 C기능이 있는데 얘네가 그때그때 하나의 힙에 메모리를 할당했다고 치자. 그런 다음 B기능이 더이상 필요가 없어서 B기능에서 할당한 메모리를 다 해제하면? 속도도 느릴 뿐더러, 힙 메모리의 파편화가 심해진다.
그런데 만약 기능별로 고유의 힙 메모리 영역을 갖도록 하면 어떨까? 기능이 소멸할 때 그냥 해당 기능이 사용하는 힙 메모리 영역을 통째로 언로드하면 된다. 속도도 빠르고 메모리 파편화의 걱정도 없다. 게다가 기능 사용 중 로컬리티도 더 좋아질 것이다.
만약 이런 다이나믹 힙을 쓰레드 단위로 해주면 어떨까?
=>
위에서 언급한 장점을 가져가면서도, 메모리의 할당과 해제 관점에서 추가적으로 이득이 있다. 쓰레드에서 메모리를 할당할 때, 같은 주소에 두 쓰레드가 동시에 메모리를 할당할 수 있으므로, 이런 상황을 방지하기위한 쓰레드 동기화처리가 필요한데, 만약 쓰레드별로 할당하는 힙 메모리 영역이 다르다면 동기화에 소비되는 자원을 아낄 수 있다.
.
페이지 폴트 (page fault)
페이지가 메인 메모리에 존재하지 않는 것. 캐시 미스처럼 당연히 느려질 수 밖에 없다.
.
MMF (Memory Mapped File)
파일의 일부 영역을 가상메모리 일부에 연결시키는 메커니즘 (메모리에 존재하는 데이터를 파일에 실시간 저장한다고 생각하면 됨)
.
COW (copy on write)
어떤 데이터를 여러 개의 객체(쓰레드가 될지도)가 들고있다고 해보자. 그리고 이 데이터는 객체마다 달라질 수 있다. 그리고 대부분의 상황에서 읽기만 한다.
읽기만 한다면, 객체마다 데이터를 따로 가지고 있을 필요가 없음. 하나를 공유하면 됨.
그런데 데이터 쓰기가 발생한다면? 그때 데이터를 따로 복사해와서 쓴 다음 내껄 갖는거임 (ex. Unity ECS에서 Shared Component 느낌)