본문 바로가기

WinAPI/기본 문법

VirtualAlloc() 함수

VirtualAlloc() -> 가상메모리를 사용하기 위해 가장 많이 사용, malloc() 보다 발전된 형태

Reserve(예약), Commit(확정)이 가능

 

* 예약의 경우 물리적 메모리는 전혀 소요되지 않는다. 확정에만 가상메모리가 실제로 할당된다.

 

 

PVOID VirtualAlloc(
    PVOID pvAddress,
    SIZE_T dwSize,
    DWORD fdwAllocationType,
    DWORD fdwProtect);

 

 

malloc() 과의 차이점

-> malloc()의 경우 확정 상태만 가능(예약이 없다.)

-> malloc()은 스택프레임에서 약 2MB정도만 할당할 수 있는 단점이 있다.(VirtualAlloc()을 사용해야함, 안그러면 StackOverflow가 발생)

 

 

* VirtualFree() 함수를 통해 가상메모리를 Release 할 수 있다.(사용 후 이 함수로 반드시 해제해 주어야 함)

 

*Tip)

작은 메모리 할당시에는 malloc이 좋다.

 

 

메모리를 예약/할당할때 주의할 점

1. Address매개변수는 시스템의 Allocation 단위의 배수(현재까지 알려진 모든 윈도우에서는 64KB)이어야만 하며 64KB(0x00010000)이하의 주소는 예약할 수 없다. 만약 Allocation의 배수가 되지 않는다면 Allocation단위의 내림을 수행한다. - MEM_RESET은 예외

2. Reaserv혹은 Commit할 수 있는 크기는 반드시 시스템의 Page단위의 배수가 되어야만 한다. 만약 그렇지 않다면 Page단위의 올림이 발생한다. - MEM_RESET은 예외

3. Reserved와 COMMIT의 보호속성은 서로 다를 수 있다. 최종적으로 적용되는 보호속성은 COMMIT때 지정한 속성으로 지정된다.

4. 일반적으로 RESERVED와 COMMIT은 분리해서 작업하나 OR연산자를 통해 한번에 수행할 수도 있다.

 

할당속성(AllocationType)

영역 예약에 관련된 Flag 특수한 Flag
MEM_COMMIT
MEM_RESERVE
MEM_RESET
MEM_TOP_DOWN
MEM_LARGE_PAGES
MEM_PHYSICAL
MEM_WRITE_WATCH
  • MEM_COMMIT : 예약된 주소공간과 물리적 저장소를 매핑하는 역활을 한다.
  • MEM_RESERVE : 사용자 주소공간에 대해 일정한 영역을 예약하는 역활을 한다.
  • MEM_RESET : 지정된 공간에 대하여 수정사항이 없다고 커널에 알려준다.
                          이 경우 커널은 해당 영역이 페이징 될 필요가 없다고 판단하게 되므로 Performance에 대하여 약간의 이점이 생긴다. 다만 해당 영역이 0으로 초기화 되었다고는 장담할 수는 없다.
    MEM_RESET을 사용할 때에는 주의할 점이 있는데 다른 할당속성과는 조금 다른게 영역이 결정된다는 점이다.
    MEM_RESET을 사용하였을 때에는 주소에 대하여 할당단위의 올림, 크기에 대해서는 페이지단위의 내림이 수행된다.
    사용자가 지정한 곳 이외의 영역에 중요한 데이타가 있을 경우 이를 보호하기 위함이다.
  • MEM_TOP_DOWN : 영역의 예약시 상위 주소부터 예약하도록 한다.
  • MEM_LARGE_PAGES : CPU에서 큰 페이지 할당기능을 제공할 경우 큰 페이지 할당을 사용한다. 단 이때 아래와 같은 몇 가지 조건을 만족해 주어야만 한다.
    1. GetLargePagesMinimum함수가 반환하는 값의 배수여야 한다.
    2. MEM_COMMIT | MEM_RESERVE가 함께 지정되어야만 한다. Commit과 Reserve를 분리해서 수행할 수 없다.
    3. 반드시 PAGE_READWRITE를 지정해 주어야만 한다.
    4. 관리자 권한으로 해당 사용자에 대하여 페이지 잠금권한이 부여되어 있어야만 한다.
    LargePages속성을 통해 할당된 페이지는 페이징 불가능 영역으로 설정되어 항상 그 내용이 램에 유지되게 한다. 따라서 속도상의 이점이 있을 수 있으나 그 만큼 공유하여 사용할 수 있는 RAM의 크기는 줄어들게 된다.
  • MEM_PHYSICAL : 차후 AWE에서 사용하게 되며 프로세스 주소공간보다 큰 RAM에 대한 접근이 필요하거나 페이징 되지 않도록 하여 속도향상을 요구할 때 사용한다.
  • MEM_WRITE_WATCH : 해당영역에 쓰기 작업이 발생하였을 때 감시하기 위해 사용한다.

 

보호속성(ProctectionType)

PAGE_EXECUTE 
PAGE_EXECUTE_READ
PAGE_EXECUTE_READWRITE
PAGE_GUARD
PAGE_NOACCESS
PAGE_NOCACHE
PAGE_READONLY
PAGE_READWRITE
PAGE_WRITECOPY
  • PAGE_EXECUTE : 해당 페이지는 실행할 수 있다. 그외의 시도는 접근 위반을 일으킨다.
  • PAGE_EXECUTE_READ : 해당 페이지는 읽기, 실행이 가능하다.
  • PAGE_EXECUTE_READWRITE : 해당 페이지는 읽기, 쓰기, 실행이 가능하다.
  • PAGE_GUARD : 해당페이지에 대한 쓰기/읽기 시도시 STATUS_GUARD_PAGE Exception을 발생시킨 후 PAGE_GUARD속성을 제거하도록 한다.
    주로 stack구조에서 사용된다.
  • PAGE_NOACCESS : 해당 페이지에 대한 모든 작업 - 읽기, 쓰기, 실행 - 에 대하여 모두 접근 위반을 일으키도록 한다.
  • PAGE_NOCACHE : 해당 페이지에 cache를 수행하지 않도록 설정한다.  이 경우 보통 보다 더 자주 업데이트를 진행하기 때문에 속도가 떨어질 수 있다.
    이러한 이용은 드라이버를 제작할 경우에 유용하나 일반적인 어플리케이션에서는 Cache를 사용하는 것이 더 낮다.
  • PAGE_WRITECOPY : 해당 페이지에 대하여 Copy On Write매커니즘을 사용할 수 있도록 한다.

 

 

출처 : http://spec98.egloos.com/v/4365938

 

spec의 정리노트 : VirtualAlloc

PVOID VirtualAlloc(     PVOID pvAddress,     SIZE_T dwSize,     DWORD fdwAllocationType,     DWORD fdwProtect); 가상메모리를 사용하기 위해 가장 많이 사용하게 되는 WinAPI중 하나이다. 이 API는 크게 두 가지 역활

spec98.egloos.com