메모리 상태 :
페이지의 개수 = 가상 메모리의 크기 / 페이지 하나당 크기
페이지 개수는 가상 메모리의 크기에 비례하며(가상 메모리는 몇 비트 환경인지에 비례 (ex. 32비트 4GB)),
모든 페이지는 Reserve, Commit, Free 세가지 중 하나의 상태를 지닌다.
Commit : 물리 메모리에 할당된 상태
Reserve : Free 와 Commit 의 중간상태이다. 해당 번지에 대해 예약을 한다.
다른 메모리 함수가 물리 메모리에 해당 번지에 할당하지 못하도록 한다.
하지만 물리 메모리의 소비는 발생하지 않는다.
Free : 물리 메모리 할당이 이뤄지지 않은 상태
메모리 할당의 시작점과 단위 확인 :
가상 메모리 시스템은 페이지 단위로 관리된다.
페이지의 중간 위치에서부터 할당을 시작할수 없으며, 페이지 크기의 배수 단위로 할당한다.
Allocation Granularity Boundary : 메모리 할당의 시작 주소가 되는 기본 단위
(참고 : 메모리가 지나치게 조각나는것과 관리의 효율성을 이유로 페이지 크기의 배수보다 더 넓은 값을 가진다)
Allocation Granularity Boundary 과 페이지 크기 확인 :
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCHAR *argv[])
{
SYSTEM_INFO si;
DWORD allocGranularity;
DWORD pageSize;
GetSystemInfo(&si);
pageSize = si.dwPageSize;
allocGranularity = si.dwAllocationGranularity;
_tprintf(_T("Page Size : %u Kbyte \n"), pageSize/1024);
_tprintf(_T("Allocation granularity : %u Kbyte \n"), allocGranularity/1024);
return 0;
}
가상 메모리 컨트롤 :
페이지 상태를 RESERVE 나 COMMIT 로 변경할때 사용하는 함수
LPVOID VirtualAlloc(
LPVOID lpAddress, // 예약 및 할당하고자 하는 메모리의 시작 주소
// (일반적 NULL 전달, RESERVED -> COMMIT 일때 해당페이지 시작 주소 지정)
SIZE_T dwSize, // 할당하고자 하는 메모리의 크기를 바이트 단위로 지정
// 메모리의 할당은 페이지 크기 단위로 결정
DWORD flAllocationType, // 메모리 할당의 타입.
// RESERVE : MEM_MRESERVE, COMMIT : MEM_COMMIT
DWORD flProtect // 페이지별 접근방식에 제한을 두는 용도
// RESERVE 상태로 변경할때는 접근을 허용하지 않는 PAGE_NOACCESS ,
// COMMIT 상태로 변경할때는 읽고/쓰기 모드인 PAGE_READWRITE 전달
);
함수 호출이 성공하면 할당이 이뤄진 메모리의 시작 주소를 리턴
할당된 페이지를 되돌리는 함수
BOOL VirtualFree(
LPVOID lpAddress, // 해제할 메모리 공간의 시작 주소
SIZE_T dwSize, // 해제할 메모리 크기를 바이트 단위로 지정
DWORD dwFreeType // MEM_DECOMMIT : 해당 페이지의 상태를 RESERVE 상태로 되돌린다.
// MEM_RELEASE : 해당 페이지의 상태를 FREE 상태로 되돌린다.
// 두번째 전달인자 dwSize 는 반드시 0 이어야 한다.
);
힙 컨트롤 :
디폴트 힙(Default Heap) :
디폴트 힙을 구성하는 페이지들은 RESERVE 상태이다. 일부는 성능을 위해 COMMIT 상태일수도 있다.
C 언어의 malloc 함수와 free 함수, C++ 언어의 new와 delete 를 사용해서 힙영역을 사용할 경우
프로세스를 생성할때 생성되는 힙, 즉 1M 바이트 크기의 디폴트 힙에 메모리를 할당한다.
(COMMIT 와 RESERVE 상태를 오간다)
프로세스에 기본적으로 할당되는 힙이며 프로세스 힙(Process Heap)라고도 한다.
디폴트 힙 컨트롤 :
디폴트 힙의 기본 크기는 1MB 이다. 링커(Linker)옵션을 통해 크기를 변경할 수 있다.
/HEAP : reserve, commit (ex. /HEAP 0x200000, 0x10000 : 디폴트 힙의 크기 : 2MB, COMMIT 크기 : 64KB)
힙은 동적이라 기본 크기 1MB 로 생성이 된 후 필요에 따라 그 크기가 Windows 시스템에 의해 자동으로 늘어난다.
Windows 시스템 힙(Dynamic Heap) :
Windows 시스템 함수를 통해 여러 힙을 추가로 생성할 수 있다.
가상 메모리 범위 내에서 프로세스 생성시 만들어지는 디폴트 힙 이외에 필요로 하는 힙을 얼마든지 생성할 수 있다.
힙(Dynamic Heap) 생성이 가져다 주는 이점 :
1. 메모리 단편화의 최소화에 따른 성능 향상 :
2. 동기화 문제에서 자유로워짐으로 인한 성능 향상 :
힙은 쓰레드가 공유하는 메모리 영역이다. 따라서 둘 이상의 쓰레드가 동시접근 할때 문제가 발생할수 있으므로
Windows 내부적으로 동기화처리를 해준다.(여기서 동기화는 메모리 할당과 해제)
같은 주소 번지에 둘 이상의 쓰레드가 동시에 메모리를 할당 및 해제하는 상황이 발생할 경우 메모리 오류(Corrupt)가
발생하므로 디폴트 프로세스 힙은 동기화 처리를 하는데 쓰레드마다 독립된 힙을 가지고 있다면
이러한 동기화가 필요없으므로 성능이 향상된다.
힙(Dynamic Heap) 컨트롤 :
힙을 생성하는 함수 :
HANDLE HeapCreate(
DWORD flOptions, // 생성되는 힙의 특성을 부여 (0 을 전달시 가장 일반적인 힙 생성)
// HEAP_GENERATE_EXCEPTIONS : 오류 발생시 NULL이 아닌 예외 발생
// HEAP_NO_SERIALIZE : 생성된 힙의 메모리 할당과 해제에 대해
// 동기화 처리를 하지 않는다.
// 둘 이상의 속성을 비트 단위 연산자 OR( | )로 동시 지정 가능
SIZE_T dwInitialSize, // dwMaximumSize 에서 지정한 메모리 중에서
// 초기에 할당할 COMMIT 페이지를 지정한다
SIZE_T dwMaximumSize // 생성되는 힙의 크기 결정.
// 지정하는 크기에 해당하는 페이지의 수만큼 RESERVE 상태가 된다.
// 0이 아닐 경우 힙은 증가가능한 메모리(Growable Heap)가 된다
);
힙을 소멸하는 함수 :
BOOL HeapDestroy(
HANDLE hHeap // 반환하고자 하는 힙의 핸들
);
힙에 메모리를 할당하는 함수 :
LPVOID HeapAlloc(
HANDLE hHeap, // 메모리 할당이 이뤄질 힙의 핸들
DWORD dwFlags, // HEAP_GENERATE_EXCEPTIONS : 오류 발생시 NULL이 아닌 예외 발생
// HEAP_NO_SERIALIZE : 함수호출시 동기화 처리되지 않는다.
// (HeapCreate 함수호출에서 지정했다면 중복지정할 필요는 없다)
// HEAP_ZERO_MEMORY : 할당된 메모리는 0으로 초기화
// 둘 이상의 속성을 비트 단위 연산자 OR( | )로 동시 지정 가능
SIZE_T dwBytes // 할당하고자 하는 메모리의 크기를 지정
// (증가가능한 힙이 아닐 경우 최대 크기 0x7FFF8)
);
힙에 메모리를 해제하는 함수 :
BOOL HeapFree(
HANDLE hHeap, // 해제할 메모리를 담고 있는 힙을 지정
DWORD dwFlags, // HEAP_NO_SERIALIZE 가 인자로 올 수 있다, 일반적 : 0
// (HeapCreate 함수호출에서 지정했다면 중복지정할 필요는 없다)
LPVOID lpMem // 해제할 메모리의 시작 주소 지정
);
반응형
'운영체제 & 병렬처리 > 시스템프로그래밍' 카테고리의 다른 글
구조적 예외 처리 - Structured Exception Handling(SEH) (0) | 2012.12.25 |
---|---|
ESP 와 EBP (0) | 2012.12.15 |
Shared Lock(공유 잠금), Exclusive Lock(독점 잠금) (0) | 2012.12.14 |
표준 검색 경로 (0) | 2012.11.01 |
FAQ - 윈도우프로그래밍 (0) | 2012.11.01 |