CPU와 프로그래머 관점에서의 메모리는 가상 메모리.
4GB의 가상 메모리가 있고 물리 메모리가 별도로 존재하며, 가상 메모리가 물리 메모리에 맵핑되는 형태.
가상 메모리는 페이지 단위로 구성됨.
4GB의 메모리 공간이 있을 경우, 페이지 개수 = 4GB / 페이지 크기
윈도우즈는 페이지(가상 메모리)를 관리할 때 특성을 부여.
COMMIT, FREE, RESERVE => 페이지는 다음 세 상태 중 한 가지 상태를 지닌다
FREE
COMMIT

일 년 내내 동작하는 프로그램이 있다고 가정.
이 프로그램은 보통 메모리 공간을 많이 차지하지 않지만, 특별한 경우에는 1만 메모리를 요구함.
해당 경우를 위해 처음 메모리를 할당할 때 1만 메모리를 미리 할당해둬야 하지만, 이는 매우 비효율적.
5개의 페이지를 Commit 상태로 두었으나 실제로는 2개만 사용하고, 나머지 3개는 나중을 위해 미리 잡아둔다면 비효율적. Commit을 통해 해당 페이지는 물리 메모리와 이미 연결된 상태이기 때문에 남들도 할당받을 수 없음.
페이지 2개만 잡아두고 필요할 때 추가적으로 다른 위치에 페이지를 잡아둔다면?
메모리 공간을 순차적으로 할당해 하나의 메모리 구조로 구성하는 것은 프로그래밍 시 중요한 사항.
추후 메모리 공간을 할당한다는 건 연결된 메모리 구조가 아니기 때문에 순차적인 접근 또한 불가능. 따라서 이는 논외의 대상.
1) 연결된 메모리 공간이 필요
2) 그렇다고 미리 할당해두면 낭비가 심하기 때문에 낭비를 해결하고 싶음
이를 해결하기 위해 Reserve, 페이지의 예약 상태로 두는 개념이 등장.

RESERVE
기본적으로 모든 메모리 공간은 Free상태.
가상 메모리 할당을 할 때, 윈도우즈는 메모리는 페이지 단위로 관리하기 때문에 아무 주소부터 Commit이나 Reserve 상태로 바꿀 수 없음.
메모리 할당 시 어디서부터 할당해야하는지 기준과 최소 할당 단위가 존재.
메모리 단편화
물리 메모리에서 메모리 공간이 작은 조각으로 나뉘어 사용 가능한 메모리가 충분히 존재함에도 불구하고 사용 불가능한 상태.
// 마치 malloc()과 같음. malloc()은 힙 메모리, 아래 함수는 가상 메모리(근데 이는 사실 힙 메모리)
// malloc()은 COMMIT/FREE 상태로만 가능하지만 아래 함수는 RESERVE 상태도 가능함.
LPVOID VirtualAlloc(
LPVOID lpAddress, // 할당의 시작 주소.
SIZE_T dwSize, // 할당의 크기
DWORD flAllocationType, // MEM_RESERVE(거의 쓸일 없음.) or MEM_COMMIT
DWORD flProtect // PAGE_NOACCESS or PAGE_READWRITE
);
// 반환: 할당이 이뤄진 메모리의 시작번지
// VirtualFree()는 COMMIT 상태를 FREE 상태로 끌어내리기도 하지만,
// RESERVE 상태를 FREE 상태로 끌어내리기도 함.(잘 안씀)
// 또한 COMMIT 상태를 RESERVE상태로 끌어내리기도 함.
// 결국 아래 함수는 할당 받은 가상 메모리 공간을 반환하는데 의의가 큼.
BOOL VirtualFree(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType // MEM_DECOMMIT(COMMIT->RESERVE) or MEM_RELEASE
);
가상 메모리 컨트롤의 경우, 가상 메모리 공간의 일부를 Commit, Free, Reserve 상태로 둘 수 있었음. 해당 가상 메모리를 힙으로 봐도 무방.
아래는 비디오 대여 프로그램의 내부 이미지.
들어올 데이터의 크기가 미리 정해져 있지 않을 경우 보통 list 자료 구조를 사용하는데, list는 메모리를 반환할 때 일일히 들어가서 지워야 함. 즉 사용자 최대수를 지우려 한다면 최대수가 대여한 비디오 목록까지 하나하나 지워줘야 하는데, 하나의 힙 안에 두 사용자를 위한 데이터가 함께 있어서 최대수와 관련된 데이터만 선별적으로 삭제해줘야 함. 이는 에러가 발생할 확률이 높음.
디폴트 힙(Default Heap)윈도우즈에서는 사용자가 디폴트 힙 이외에 힙을 만들 수 있게 해주는데, 이를 힙 컨트롤이라고 한다.

동적 힙(Dynamic Heap)
가상 메모리 컨트롤은 예약을 통해 메모리의 낭비하지 않는 효율성에 초점이 맞춰져 있었다면, 다이나믹 힙은 데이터의 관리에 초점을 맞춘다.
4GB의 메모리 공간이 있다면, 해당 공간이 데이터/힙/스택으로 꽉 차는게 아니라 일부는 데이터 영역, 일부는 (디폴트)힙 영역으로 구성되고 나머지는 내버려둠. 이 영역에 사용자가 추가로 힙을 생성할 수 있음.
이전에 가상 메모리 컨트롤을 할 때는 일부 가상 메모리를 할당받은 다음 할당받은 메모리의 주소를 받아 상태를 지정해서 사용했음. 이는 디폴트 힙도, 다이나믹 힙도 아님. 이를 힙으로 볼지 가상 메모리를 다른 용도로 사용한다고 볼지는 상관 없다.
그러나 힙은 Runtime 때 크기가 할당 및 결정된다는 기준이 있음. 가상 메모리 컨트롤을 할 때 가상 메모리 공간 또한 Runtime 때 할당받기 때문에 해당 가상 메모리 공간을 힙이라고 볼 수 있음.

메모리를 파일에 맵핑시키는 개념.
파일의 일부 메모리 공간을 프로세스의 가상 메모리에 연결. 그리고 맵핑된 프로세스의 가상 메모리에 데이터를 쓰면 해당 위치만큼 offset된 파일의 위치에 데이터를 쓰는 효과를 얻을 수 있음.


MMF의 장점
프로그래밍의 편리성
파일에 저장되어 있는 데이터를 정렬해야 한다면 파일 데이터를 모두 메인 메모리로 읽어들여 저장한 뒤 정렬, 그리고 다시 파일로 저장해야 하는 불편함이 있음. MMF를 이용한다면 데이터를 읽고 쓰는 과정 없이 프로세스 가상 메모리 안에서 정렬하면 파일에도 반영이 된다.
데이터를 읽고 쓸 때마다 매번 파일에 반영할 필요 없다.
프로세스는 가상 메모리 안에서 데이터를 읽고 쓰기 때문에 최신 메모리가 가상 메모리에 있음. 주기적으로, 특별한 상황이 발생했을 때만 파일에 해당 정보를 반영해도 문제가 되지 않음. 빈번한 I/O가 발생하는 곳에서는 가장 최근의 데이터를 유지해주고 최신 데이터가 저장된다는 보장만 있다면 주기적, 상황적으로 I/O를 발생시켜도 문제가 없음.
즉 메모리 공간이 파일에게 캐쉬 역할을 함.

HANDLE hFile = CreateFile(...);
HANDLE hMapFIle = CreateFileMapping(hFile, ...);
메모리 맵핑을 위해 해당 파일의 정보를 담은 파일 연결 오브젝트를 생성.
TCHAR* pWrite = (TCHAR*)MapViewOfFile(hMapFile, ...);
생성된 연결 오브젝트를 인자로 전달해 가상 메모리에 연결 요청.
연결하면 포인터 pWrite가 반환되는데, 해당 위치부터 반환 타입의 크기만큼 접근 가능.