'메모리 할당'에 해당되는 글 1건

  1. 2010.03.24 메모리 컨트롤

메모리 상태 :


페이지의 개수 = 가상 메모리의 크기 / 페이지 하나당 크기

페이지 개수는 가상 메모리의 크기에 비례하며(가상 메모리는 몇 비트 환경인지에 비례 (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                 // 해제할 메모리의 시작 주소 지정
);

Posted by Dakuo