레이블이 WinApi인 게시물을 표시합니다. 모든 게시물 표시
레이블이 WinApi인 게시물을 표시합니다. 모든 게시물 표시

2020년 7월 1일 수요일

WinAPI - 가상메모리 조작

1. 가상 주소 조작

가상 메모리를 사용함으로서 실제 주소와 가상 주소가 분리된다. malloc, new 같은 함수는 가상 메모리를 실질적으로 할당하는데, 이렇게 메모리 차원에서 할당을 하지 않고 가상주소 차원에서 조작할 수 있다. 이 경우 단위는 페이지이며 처리해야 할 수준이 주소에서 끝나므로 단위가 큰 경우 효율적으로 사용할 수 있다.

LPVOID VirtualAlloc ( LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);

BOOL VirtualFree ( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType)

flAllocationType 은 아래의 플래그이다.

MEM_RESERVE

물리적인 메모리의 할당없이 주소공간만 예약한다

MEM_COMMIT

물리적인 메모리를 확정한다.

이러면 malloc과 거의 같아진다.

MEM_TOPDOWN

가급적 높은 번지에 메모리를 할당한다.

flProtect 는 아래의 플래그이다.

PAGE_READONLY

읽기만 가능하다

PAGE_READWRITE

읽고 쓰가 다 가능하다

PAGE_NOACCESS

읽기, 쓰기 모두 불가능

PAGE_GUARD

스택 확장용이라는데 사용법 아직 이해 못함

아래는 dwFreeType 의 플래그이다.

MEM_DECOMMIT

확정된 페이지 해제

MEM_RELEASE

예약된 페이지 해제

해제 함수의 경우 0 이 성공이고 -1 이 실패임에 주의.

ptr = (int*)VirtualAlloc(NULL, sizeof(int)*10, MEM_RESERVE_PAGE, PAGE_READWRITE);

ptr = (int*)VirtualAlloc(ptr, sizeof(int)*10, MEM_COMMIT, PAGE_READWRITE);

위 코드의 방식으로 사용해서 페이지 예약, 확정을 조절하는게 주요 사용법이다.

대용량 메모리의 할당을 유동적으로 조절할 때 주로 사용한다.

2. 메모리 맵 파일

용량이 큰 파일의 경우 메모리에 다 올릴 수가 없다. 그런 경우 가상메모리의 일부를 디스크와 연결하여 메모리에 파일을 전체를 올리지 않고 페이지 단위로 파일의 부분만 올리는데 이걸 메모리 맵핑이라고 한다.

또한 Win32에서 프로세스간 메모리를 공유하는 유일한 합법적인 방법이다. 여러개의 프로세스가 하나의 메모리 맵 파일을 동시에 접근할 수 있기 때문이다.

HANDLE CreateFileMapping ( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName);

hFile 은 CreateFile로 오픈한 핸들이다. 이 때 공유 설정은 0 으로 하는 것이 바람직하다.

CreateFile 로는 핸들만 얻을 뿐 버퍼에 내용을 채우지 않는다. 오해주의.

공유 메모리를 위해선 INVALID_HANDLE_VALUE 를 넣는다.

lpFileMappingAttributes 는 보안 정보와 관련되었다 하는데 대개 NULL 을 준다고 한다.

lpProtect 는 아래의 플래그이다.

PAGE_READONLY

hFile 이 GENERIC_READ 로 열려있어야 한다. 읽기 전용.

PAGE_READWRITE

hFile 이 GENERIC_WRITE 로 열려있어야 한다. 읽고 쓰기 전용

대용량의 경우 더더욱 쓰기 속도는 매우 느리니 주의.

PAGe_WRITECOPY

읽고 쓰되 쓰는 즉시 복사한다.

dwMaximumSizeHigh, dwMaximumSizeLow 는 합쳐져서 생성될 맵핑 오브젝트의 최대 크기를 지정한다.

0, 0 을 지정하면 hFile 에 지정된 파일의 크기가 사용된다.

메모리 공유시 0, MAXSHAREDMEMORY 를 사용한다.

lpName 은 생성할 오브젝트의 이름이다. 필요없을 경우 NULL 을 넣는다.

공유 메모리를 사용시

LPVOID MapViewOfFile ( HANDLE hFileMappingObject, DWORD dwDesireAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMaps );

위 함수로 파일의 일부분을 메모리에 올린다.

dwDesireAccess 는 아래의 플래그이다. flProtect 인수와 호환되야한다.

FILE_MAP_WRITE

읽고 쓸 수 있다.

FILE_MAP_READ

읽을 수 있다.

FILE_MAP_ALL_ACCESS

읽을 수도 쓸 수도 있다.

FILE_MAP_COPY

읽고 쓰되, 쓰기 즉시 복사를 한다.

dwNumberOfBytesToMaps 은 맵핑할 뷰의 크기를 지정한다. 0 이면 전체이다.

BOOL UnmapViewOfFile (LPCVOID lpBaseAddress );

MapViewOfFile 에서 얻어온 포인터는 이 함수로 해제한다.

CreateFileMapping 으로 생성한 파일 핸들은 CreateFile 과 똑같이 CloseHandle 로 해제한다.

아래는 책에 있는 메모리 공유 예제인데 신기방기.

클래스 이름만 바꿔서 파일 두개 만들어서 실행하면 된다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

#define WM_SYNCSHAREMEMORY WM_USER+1

#define MAXSHAREMEMORY 1024

#define ID_EDIT 100

HWND hEdit;

HANDLE hFMap;

TCHAR *PtrlnFile;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT ps;

HWND hTarget;

LPCTSTR Mes = TEXT("메모리 맵 파일을 사용하여 두 프로세서가 메모리를 공유하는 예제");

switch (message)

{

case WM_CREATE:

hEdit = CreateWindow(TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL

|ES_MULTILINE, 10, 10, 500, 200, hWnd, (HMENU)ID_EDIT, hInst, NULL);

SendMessage(hEdit, EM_LIMITTEXT, MAXSHAREMEMORY, 0);

hFMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,

0, MAXSHAREMEMORY, TEXT("MEMSHAREMAPPING"));

PtrlnFile = (TCHAR*)MapViewOfFile(hFMap, FILE_MAP_ALL_ACCESS, 0, 0, MAXSHAREMEMORY);

break;

case WM_COMMAND:

switch (LOWORD(wParam))

{

case ID_EDIT:

switch (HIWORD(wParam))

{

case EN_CHANGE:

GetWindowText(hEdit, PtrlnFile, MAXSHAREMEMORY);

hTarget = FindWindow(NULL, TEXT("MemShared1"));

if (hTarget)

SendMessage(hTarget, WM_SYNCSHAREMEMORY, 0, 0);

break;

}

}

break;

case WM_SYNCSHAREMEMORY:

SetWindowText(hEdit, PtrlnFile);

break;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

TextOut(hdc, 10, 220, Mes, lstrlen(Mes));

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

UnmapViewOfFile(PtrlnFile);

CloseHandle(hFMap);

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

List