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
'WinAPI > 기본 문법' 카테고리의 다른 글
유니코드, 멀티바이트 차이점 (1) | 2022.09.28 |
---|---|
<Window API> 바이너리 파일 Read & Write 관련 함수들 (0) | 2022.02.11 |