15. 가상메모리,...

23
1 15. 15. 가상 가상 메모리 메모리 , , 프로세스 프로세스 2 1. 메모리 할당 가상 메모리 OS는 4G 까지 메모리(단지 주소공간, 물리적인 메모리와 연결 가능성이 있는 메모리 번지) 관리 가능 사용하지 않는 부분은 하드 디스크의 페이징 파일에 저장하여 사용 가능 RAM을 늘린다. (RAM+하드디스크의 페이징 파일) Win32에서 추가된 가상 메모리 할당 함수들 1. 메모리를 예약 상태로 할당할 수 있다. • 예약이란 물리적인 메모리를 소비하지 않으면서 주소 공간만을 미리 할당해 놓는 방법을 말한다. 2. 할당한 메모리의 액세스 권한을 지정할 수 있다. 가상 메모리 함수로 할당한 메모리는 읽기 전용, 액세스 금지 속성을 가질 수 있어 실수로 인한 데이터 파괴를 막을 수 있다. LPVOID VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); lpAddress : 할당하고자 하는 메모리 번지를 지정하되 NULL이면 시 스템이 알아서 할당 번지를 지정해 준다. dwSize : 할당하고자 하는 메모리의 양을 바이트 단위로 지정한다. flAllocationType : 할당 방법 ( MEM_RESERVE, MEM_COMMIT) flProtect : 할당한 페이지의 액세스 타입을 지정하며 보통 PAGE_READWRITE로 지정한다.

Transcript of 15. 가상메모리,...

Page 1: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

1

15.15.

가상가상 메모리메모리, , 프로세스프로세스

2

1. 메모리 할당• 가상 메모리

– OS는 4G 까지 메모리(단지 주소공간, 물리적인 메모리와 연결 가능성이있는 메모리 번지) 관리 가능

– 사용하지 않는 부분은 하드 디스크의 페이징 파일에 저장하여 사용 가능한 RAM을 늘린다. (RAM+하드디스크의 페이징 파일)

• Win32에서 추가된 가상 메모리 할당 함수들

– 1. 메모리를 예약 상태로 할당할 수 있다.

• 예약이란 물리적인 메모리를 소비하지 않으면서 주소 공간만을 미리할당해 놓는 방법을 말한다.

– 2. 할당한 메모리의 액세스 권한을 지정할 수 있다.

• 가상 메모리 함수로 할당한 메모리는 읽기 전용, 액세스 금지 속성을가질 수 있어 실수로 인한 데이터 파괴를 막을 수 있다.

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

• lpAddress : 할당하고자 하는 메모리 번지를 지정하되 NULL이면 시스템이 알아서 할당 번지를 지정해 준다.

• dwSize : 할당하고자 하는 메모리의 양을 바이트 단위로 지정한다.

• flAllocationType : 할당 방법 ( MEM_RESERVE, MEM_COMMIT)

• flProtect : 할당한 페이지의 액세스 타입을 지정하며 보통PAGE_READWRITE로 지정한다.

Page 2: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

3

1. 메모리 할당– LPVOID VirtualFree (LPVOID lpAddress, DWORD dwSize,

DWORD dwFreeType);

• lpAddress : 해제하고자 하는 메모리의 선두 번지

• dwSize : 해제하고자 하는 메모리의 크기

• dwFreeType : MEM_DECOMMIT (확정된 페이지를 확정 해제) MEM_RELEASE(예약된 페이지를 예약 해제 한다.)

4

2. 예약과 확정– win32 프로세스가 가지는 4G의 가상 메모리는 “페이지”라는 단위

로 구성된다.

– 인텔 계열의 CPU에서는 한 페이지의 크기는 4K바이트이다.

– 윈도우는 페이지 단위로 가상 메모리를 관리한다.

• 할당하거나 해제하는 단위가 페이지 단위이다.

– 가상 메모리를 구성하는 각 페이지는 다음 세 가지 상태 중 하나의상태로 존재한다.

• 1. 자유영역 (Free) : 사용되지 않는 자유 영역이다.

• 2. 예약 (Reserved) : 장래 사용을 위해 예약만 되어 있는 페이지이며물리적인 메모리가 할당되어 있지 않다.

• 3. 확정(Committed) : 물리적 메모리가 할당되어 잇는 상태이며 바로사용할 수 있다.

– 할당 영역의 크기는 반드시 페이지 단위의 배수가 된다.

• 10K의 크기만큼 할당을 요청했다면 실제로 할당되는 영역의 크기는12K가 될 것이다.

Page 3: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

5

3. 보호 속성– VirtualAlloc의 네 번째 인수 fProtect는 할당하고자 하는 메모리의

액세스 타입을 지정한다.

• PAGE_READONLY : 읽기만 가능하도록 한다.

• PAGE_READWRITE : 읽기 쓰기를 가능하도록 한다.

• PAGE_EXECUTE : 실행만 가능하도록 한다.

• PAGE_EXECUTE_READ : 실행 및 읽기 기능만 가능하도록 한다.

• PAGE_EXECUTE_READWRITE : 실행,읽기,쓰기를 가능하도록 한다.

• PAGE_GUARD : 보호페이지로 지정한다. 이 페이지에 읽기, 쓰기를시도하면 STATUS_GUARD_PAGE예외가 발생하며 보호 페이지 상태가 해제된다. 메모리의 끝을 표시하는 용도로 주로 사용된다.

• PAGE_NOACCESS: 어떤 액세스도 하지 못하도록 한다.

• PAGE_NOCACHE : 캐시를 금지시킨다.

6

4. 메모리 맵 파일– 메모리 맵 파일은 하드 디스크에 존재하는 파일의 내용을 프로세

스의 주소 공간에 연결하는 기법이다.

• 파일을 메모리처럼 사용하는 기법

– 가상 주소 공간에 파일을 맵한 후 그 포인터를 사용하면 파일의 내용을 마치 메모리 다루듯이 똑같이 사용할 수 있다.

– 파일을 열고 닫고 파일 포인터를 옮기고 버퍼를 유지하는 복잡한처리를 할 필요 없이

– 메모리에 데이터를 읽고 쓰듯이 파일을 조작할 수 있다.

Page 4: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

7

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

HDC hdc;PAINTSTRUCT ps ;switch (message){case WM_CREATE:

return 0;case WM_LBUTTONDOWN:

{hdc = GetDC(hwnd);

HANDLE hFile = CreateFile("123.txt",GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);if (hFile == INVALID_HANDLE_VALUE){

MessageBox(hwnd,"파일이 없습니다.","에러",MB_OK);}else{

HANDLE hFMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);char * pData = (char *)MapViewOfFile(hFMap,FILE_MAP_READ,0,0,0);RECT rect;GetClientRect(hwnd,&rect);DrawText(hdc,pData,GetFileSize(hFile,NULL),&rect,DT_EXPANDTABS);UnmapViewOfFile(hFMap);CloseHandle(hFile);

}ReleaseDC(hwnd,hdc);

}return 0;

case WM_DESTROY:PostQuitMessage (0) ;return 0 ;

}return DefWindowProc (hwnd, message, wParam, lParam) ;

}

8

4. 메모리 맵 파일

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

– hFile : 대상 파일의 핸들 (INVALID_HANDLE_VALUE)

– lpAttribute : NULL

– flProtect :

• PAGE_READONLY : 읽기 전용의 파일 맵핑 오브젝트를 만든다. 이렇게 만들어진 메모리 맵 파일에 쓰기를 해서는 안 된다.

• PAGE_READWRITE : 읽고 쓸 수 있는 파일 맵핑 오브젝트를 만든다.

• PAGE_WRITECOPY : 쓰기를 수행하는 시점에서 별도의 복사본이 생성된다.

– dwMaximumSizeHigh, dwMaximumSizeLow : 이 인수들이 모두0이면 hFile에서 지정한 파일의 크기가 그대로 사용된다.

Page 5: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

9

4. 메모리 맵 파일– 파일 맵핑 오브젝트를 만든 후에는 이 오브젝트를 프로세스의 주

소 공간에 맵해야 한다.

– 주소 공간에 맵한 후 그 주소 공간을 사용한다.

– 주소 공간에 맵된 파일의 일부분을 파일 뷰라고 한다.

LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap

);

10

4. 메모리 맵 파일– hFileMappingObject :

• 주소 공간에 맵하려는 파일 오브젝트의 핸들

– dwDesiredAccess :

• FILE_MAP_WRITE : 읽고 쓸 수 있다.

• FILE_MAP_READ : 읽을 수 있다.

• FILE_MAP_ALL_ACCESS : 읽을 수도 있고 쓸 수도 있다.

• FILE_MAP_COPY : 읽고 쓸 수 있다. 쓰기 시도가 발생하면 데이터의복사본을 만든 후 쓴다.

– dwFileOffsetHigh, dwFileOffsetLow

• 맵핑을 시작할 오프셋 위치를 나타내는 64비트 정수를 지정한다.

• 이 값이 0이면 파일의 선두부터 맵핑이 된다.

• 오프셋은 시스템의 할당 단위(64K)의 배수여야 한다.

– dwNumberOfBytesToMap

• 맵핑할 뷰의 크기

• 0이면 파일 전체가 맵핑된다.

– UnmapViewOfFile(LPCVOID lpBaseAddress);

Page 6: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

11

프로세스프로세스

12

1. 프로세스와 스레드– 프로세스는 실행중인 프로그램의 한 인스턴스이다.

– 운영체제는 실행된 프로그램을 프로세스 단위로 관리한다.

– 프로세스는 각각 4GB의 주소 공간과 파일, 메모리, 스레드 등의객체들을 소유하며 프로세스가 종료될 때 프로세스가 소유한 자원은 운영체제에 의해 파괴된다.

– 프로세스는 실행과 동시에 스레드를 하나 만들고 스레드를 호출함으로써 스레드에게 모든 작업을 맡긴다.

– 프로세스는 최소한 한 개 이상의 스레드를 가진다.

– 프로세스와 동시에 만들어지는 스레드를 주 스레드(Primary Thread)라고 한다.

– 하나의 프로세스가 여러 개의 스레드를 만들 수 있다.

Page 7: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

13

1. 프로세스와 스레드

– lpApplicationName :

• 실행하고자 프로그램의 이름을 준다.

• 완전 경로를 주거나 파일명만 지정한 경우는 현재 디렉토리에서 파일을 찾으며 검색 경로는 사용하지 않는다.

• 이 인수를 NULL로 주고 두 번째 인수에 실행 파일명을 줄 수도 있다.

BOOL CreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );

14

1. 프로세스와 스레드– lpCommandLine

• 명령행 인수를 지정한다.

• 첫 번째 인수가 NULL일 경우 실행 파일명을 가질 수도 있으며 실행파일명과 명령행 인수를 동시에 지정하는 것도 가능하다.

– lpStartupInfo

• 새로 만든 프로세스의 메인 윈도우가 어떻게 초기화될지를 지정하는구조체이다.

• 이 구조체의 cb멤버에는 구조체의 크기가 반드시 대입되어야 한다.

– lpProcessInformation

• 생성된 프로세스의 정보를 대입 받기 위한 구조체이며 생략할 수 없다.

case WM_LBUTTONDOWN:{

STARTUPINFO si;memset(&si,0,sizeof(STARTUPINFO));PROCESS_INFORMATION pi;CreateProcess(NULL,"Notepad.exe",NULL,NULL,FALSE,NULL,NULL,NULL,&si,&pi);

}return 0;

Page 8: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

15

1. 프로세스와 스레드

typedef struct _STARTUPINFO {DWORD cb;LPTSTR lpReserved;LPTSTR lpDesktop;LPTSTR lpTitle;DWORD dwX;DWORD dwY;DWORD dwXSize;DWORD dwYSize;DWORD dwXCountChars;DWORD dwYCountChars;DWORD dwFillAttribute;DWORD dwFlags;WORD wShowWindow;WORD cbReserved2;LPBYTE lpReserved2;HANDLE hStdInput;HANDLE hStdOutput;HANDLE hStdError;

} STARTUPINFO,*LPSTARTUPINFO;

16

1. 프로세스와 스레드– cb : sizeof(STARTUPINFO)값을 대입한다.

– dwFlags : 어떤 속성을 지정할 것인가에 따라 플래그를 설정한다.

STARTF_USEPOSITON dwX,dwY 멤버가 지정하는 위치에 메인 윈도우를 배치한다.

STARTF_USESHOWWINDOW wShowWindow멤버가 지정하는 방식대로 메인 윈도우를 보여준다.

STARTF_USESIZE dwXSize, dwYSize멤버가 지정하는 크기대로메인 윈도우를 배치한다.

typedef struct _PROCESS_INFORMATION {

HANDLE hProcess;HANDLE hThread;DWORD dwProcessId;DWORD dwThreadId;

} PROCESS_INFORMATION,*LPPROCESS_INFORMATION;

Page 9: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

17

– lpProcessAttributes

– lpThreadAttributes

• 프로세스와 주 스레드의 보안 속성을 지정한다.

– bInheritHandles

• 새로 생성되는 프로세스가 페이런트로부터 핸들을 상속받을 수 있는지를 지정한다.

– dwCreationFlags

• 새로 생성되는 프로세스의 우선 순위 클래스와 프로세스 생성 옵션을지정한다.

• REALTIME_PRIORITY_CLASS : 최상위 우선권

• HIGH_PRIORITY_CLASS : 상위 우선권

• ABOVE_PRIORITY_CLASS : 상위 우선권

• NORMAL_PRIORITY_CLASS : 보통 우선권

• BELOW_PRIORITY_CLASS : 하위 우선권

• IDLE_PRIORITY_CLASS : 최하위 우선권

– lpEnvironment

• 새 프로세스의 환경 블록을 지정하는 포인터. 이 값이 NULL이면 페이런트의 환경 블록을 사용하며 보통 NULL이다.

1. 프로세스와 스레드

18

– lpCurrentDirectory

• 새 프로세스의 작업 디렉토리를 지정한다.

• NULL일 경우 페이런트의 현재 디렉토리가 새 프로세스의 작업디렉토리가 된다.

– LPTSTR GetCommandLine(VOID);

• 이 함수는 현재 프로세스의 명령행 인수를 조사해 리턴해 준다.

1. 프로세스와 스레드

Page 10: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

19

– VOID ExitProcess( UINT uExitCode );

• 이 함수가 호출되면 프로세스는 정리작업에 들어가 즉각 종료된다.

• 1. 프로세스와 연결된 모든 DLL을 종료시키기 위해 각 DLL의 DllMain함수가 호출되며 DLL들은 스스로 정리 작업을 한다.

• 2. 모든 열려진 핸들을 닫는다.

• 3. 실행중인 모든 스레드는 종료한다.

• 4. 프로세스 커널 객체와 스레드 객체는 신호상태가 되며 이 객체를기다리는 다른 프로세스는 대기상태를 해제할 수 있다.

• 5. 프로세스의 종료코드는 STILL_ACTIVE와 ExitProcess가 지정한 종료값이 된다.

– BOOL TerminateProcess( HANDLE hProcess, UINT uExitCode);

• 이 함수는 ExitProcess에 비해 종료 대상이 되는 프로세스의 핸들을인수로 가지므로 다른 프로세스를 강제로 종료시킬 수도 있다.

• 이 함수는 ExitProcess보다 훨씬 더 위험하다.

• TerminateProcess함수가 호출될 때 ExitProcess와 동일한 정리작업이 수행되나 단 연결된 DLL에게 종료사실이 통지되지 않는다.

• 어쩔 수 없이 강제로 종료해야 할 경우에만 사용한다.

1. 프로세스와 스레드

20

– 핸들은 프로세스 내에서 해당 객체를 액세스할 때 사용하는 한정적인 값이며 이 핸들을 사용하여 객체를 마음대로 조작할 수 있다.

– ID는 시스템 전역적인 값이며 다른 프로세스 ID와 절대 중복되지않는다.

– 프로세스끼리 ID를 전달해 줌으로써 목적이 되는 프로세스 핸들을다시 오픈할 수 있다.

– HANDLE GetCurrentProcess(VOID);

– HANDLE GetCurrentProcessId(VOID);

2. 프로세스 핸들

Page 11: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

21

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

HDC hdc;PAINTSTRUCT ps ;static HINSTANCE hInst;static STARTUPINFO si;static PROCESS_INFORMATION pi;switch (message){case WM_CREATE:

hInst = ((LPCREATESTRUCT)lParam)->hInstance;return 0;

case WM_LBUTTONDOWN:{

memset(&si,0,sizeof(STARTUPINFO));si.cb = sizeof(STARTUPINFO);si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;si.dwX = 200;si.dwY = 200;si.dwXSize = 100;si.dwYSize = 100;CreateProcess(NULL,"Notepad.exe",NULL,NULL,FALSE,NULL,NULL,NULL,&si,&pi);

}return 0;

case WM_RBUTTONDOWN:{

HWND hProcessWnd = FindWindow(NULL,"Process");MessageBox(NULL,"윈도우를 찾았습니다.","",MB_OK);PostMessage(hProcessWnd,WM_MYMSG,(WPARAM)pi.dwProcessId,NULL);

}return 0;

case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;EndPaint (hwnd, &ps) ;return 0 ;

case WM_DESTROY:PostQuitMessage (0) ;return 0 ;

}return DefWindowProc (hwnd, message, wParam, lParam) ;

}

22

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

HDC hdc;PAINTSTRUCT ps ;static HINSTANCE hInst;static DWORD pID;static HANDLE hProc;switch (message){case WM_CREATE:

hInst = ((LPCREATESTRUCT)lParam)->hInstance;return 0;

case WM_MYMSG:{

pID = (DWORD)wParam;hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID);char temp[256];wsprintf(temp,"Process ID : %x, Process Handle : %x",pID,hProc);MessageBox(NULL,temp,"",MB_OK);

}return 0;

case WM_LBUTTONDOWN:{

DWORD ExitCode;GetExitCodeProcess(hProc,&ExitCode);if (ExitCode != STILL_ACTIVE){

MessageBox(NULL,"프로세스 핸들이 유효하지 않습니다.","",MB_OK);}else{

TerminateProcess(hProc,NULL);pID = NULL;

}}return 0;

case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;EndPaint (hwnd, &ps) ;return 0 ;

case WM_DESTROY:PostQuitMessage (0) ;return 0 ;

}return DefWindowProc (hwnd, message, wParam, lParam) ;

}

Page 12: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

23

– Project/Settings c/c++탭의 Code Generation에서 Use run-time Library옵션을 선택

3. Thread

24

– security : SECURITY_ATTRIBUTES 구조체의 주소, 대부분 NULL

– stack_size : 0을 입력하면 기본 스텍사이즈를 사용한다.

– unsigned ( __stdcall *start_address )( void * )

– arglist : 스레드 함수로 넘어가는 변수

– initflag : CREATE_SUSPENDED면 스레드만 만들고 실행은 하지않는다.

– thrdaddr : 스레드 ID

3. Thread

uintptr_t _beginthreadex( void * security,unsigned stack_size,unsigned ( __stdcall *start_address )( void * ),void * arglist,unsigned initflag,unsigned * thrdaddr );

Page 13: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

25

typedef struct threadParam{

HWND hwnd;BOOL bCont;

}THREAD_PARAM;

unsigned int WINAPI MyThreadFunc(LPVOID lpParameter){

THREAD_PARAM * pTp = (THREAD_PARAM *)lpParameter;HWND hwnd = pTp->hwnd;

while(pTp->bCont){

HBRUSH hBrush = CreateSolidBrush(RGB(rand()%256,rand()%256,rand()%256));RECT ClietRect,rect;GetClientRect(hwnd,&ClietRect);

SetRect(&rect,rand()%ClietRect.right,rand()%ClietRect.bottom,rand()%ClietRect.right,rand()%ClietRect.bottom);HDC hdc = GetDC(hwnd);HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc,hBrush);Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);SelectObject(hdc,hOldBrush);ReleaseDC(hwnd,hdc);Sleep(100);

}return 0;

}

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

HDC hdc;PAINTSTRUCT ps ;static unsigned int ThreadID;static HANDLE hThread;static THREAD_PARAM tp;

26

switch (message){case WM_COMMAND:

switch(LOWORD(wParam)){case IDM_THREAD_START:

if (hThread == NULL){

tp.hwnd = hwnd;tp.bCont = TRUE;

hThread = (HANDLE)_beginthreadex(NULL,NULL,MyThreadFunc,(void *)&tp,NULL,&ThreadID);}else{

DWORD ExitCode;GetExitCodeThread(hThread,&ExitCode);if (ExitCode == STILL_ACTIVE )

MessageBox(NULL,"현재 스레드는 살아있습니다.","",MB_OK);else

MessageBox(NULL,"스레드는 죽었습니다.","",MB_OK);}break;

case IDM_THREAD_QUIT:tp.bCont = FALSE;break;

case IDM_THERAD_SUSPEND:SuspendThread(hThread);break;

case IDM_THREAD_RESUME:ResumeThread(hThread);break;

}return 0;

case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;EndPaint (hwnd, &ps) ;return 0 ;

case WM_DESTROY:PostQuitMessage (0) ;return 0 ;

}return DefWindowProc (hwnd, message, wParam, lParam) ;

}

Page 14: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

27

CRITICAL_SECTION cs;int XPos; unsigned int WINAPI MyThreadFunc1(LPVOID lpParameter){

THREAD_PARAM * pTp = (THREAD_PARAM *)lpParameter;HWND hwnd = pTp->hwnd;

while(pTp->bCont){

HBRUSH hBrush = CreateSolidBrush(RGB(rand()%256,rand()%256,rand()%256));RECT ClietRect,rect;GetClientRect(hwnd,&ClietRect);

SetRect(&rect,rand()%ClietRect.right,rand()%ClietRect.bottom,rand()%ClietRect.right,rand()%ClietRect.bottom);HDC hdc = GetDC(hwnd);

EnterCriticalSection(&cs);XPos = 100;Sleep(10);TextOut(hdc,XPos,0,"1번 스레드 펑션",15);LeaveCriticalSection(&cs);

HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc,hBrush);Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);SelectObject(hdc,hOldBrush);ReleaseDC(hwnd,hdc);Sleep(120);

}return 0;

}

28

unsigned int WINAPI MyThreadFunc2(LPVOID lpParameter){

THREAD_PARAM * pTp = (THREAD_PARAM *)lpParameter;HWND hwnd = pTp->hwnd;

while(pTp->bCont){

HBRUSH hBrush = CreateSolidBrush(RGB(rand()%256,rand()%256,rand()%256));RECT ClietRect,rect;GetClientRect(hwnd,&ClietRect);

SetRect(&rect,rand()%ClietRect.right,rand()%ClietRect.bottom,rand()%ClietRect.right,rand()%ClietRect.bottom);HDC hdc = GetDC(hwnd);

EnterCriticalSection(&cs);XPos = 400;Sleep(15);TextOut(hdc,XPos,0,"2번 스레드 펑션",15);LeaveCriticalSection(&cs);

HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc,hBrush);Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);SelectObject(hdc,hOldBrush);ReleaseDC(hwnd,hdc);Sleep(130);

}return 0;

}

Page 15: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

29

• 크리티컬 섹션– void InitializeCriticalSection( LPCRITICAL_SECTION

lpCriticalSection );

– void DeleteCriticalSection( LPCRITICAL_SECTIONlpCriticalSection );

• 둘 다 CRITICAL_SECTON형의 포인터를 인수로 요구한다.

– void EnterCriticalSection( LPCRITICAL_SECTIONlpCriticalSection );

– void LeaveCriticalSection( LPCRITICAL_SECTIONlpCriticalSection );

• 보호될 코드를 다음과 같이 두 함수로 감싸준다.

3. 동기화

EnterCriticalSection(&cs); //이 사이에서 공유 자원을 안전하게 액세스한다.LeaveCriticalSection(&cs);

30

case WM_CREATE:InitializeCriticalSection(&cs); return 0;

case WM_DESTROY:DeleteCriticalSection(&cs);PostQuitMessage (0) ;return 0 ;

3. 동기화

EnterCriticalSection(&cs1); EnterCriticalSection(&cs2); //이 사이에서 공유 자원을 안전하게 액세스한다.LeaveCriticalSection(&cs2); LeaveCriticalSection(&cs1);

EnterCriticalSection(&cs2); EnterCriticalSection(&cs1); //이 사이에서 공유 자원을 안전하게 액세스한다.LeaveCriticalSection(&cs1); LeaveCriticalSection(&cs2);

– 교착 상태

Page 16: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

31

• 동기화 객체– 동기화에 사용되는 객체이다.

– 프로세스,스레드처럼 커널 객체이며 프로세스 한정적인 핸들을 가진다.

– 동기화 객체는 크리티컬 섹션보다 느리기는 하지만 여러 프로그램에서 동시에 동기화가 가능하다.

• 동기화 객체 상태는 두 가지 상태 중, 한 상태를 가짐– 신호 상태 : 스레드의 실행을 허가하는 상태. 신호상태의 동기화

객체를 가진 스레드는 계속 실행.

– 비 신호 상태 : 스레드의 실행을 허가하지 않는 상태. 신호 상태가될 때까지 스레드는 블록.

• 동기화 객체는 대기함수화 함께 사용: 조건(동기화 객체 신호 여부)에따라 쓰레드의 실행을 블록/ 실행허가를 하는 함수

– DWORD WaitForSingleObject( HANDLE hHandle, DWORDdwMilliseconds );// 동기화 객체가 블록에서 신호상태가 되기를 기다림.

• dwMilliseconds : 1/1000초 단위로 지정한다. INFINITE로 지정하면무한정 기다린다.

3. 동기화

32

• WAIT_OBJECT_0 : hHandle 객체가 신호 상태가 되었다.

• WAIT_TIMEOUT : 타임 아웃 시간이 경과하였다.

• WAIT_ABANDONED : 포기된 뮤텍스

• 일단 쓰레드가 동기화 객체를 소유하면 동기화 객체는 비신호상태가 됨

• 뮤텍스– 크리티컬 섹션과 유사하다.

– 이름을 가질 수 있고 프로세스간에서도 사용이 가능하다.

– HANDLE CreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName );

• lpMutexAttributes : 보통 NULL

• bInitialOwner : 뮤텍스를 생성함과 동시에 소유할 것인지를 지정한다. TRUE이면 소유하며, 뮤텍스가 비 신호상태로 생성됨으로써 다른스레드는 이 뮤텍스를 소요할 수 없게 된다.

– 생성한 뮤텍스를 파괴할 때는 CloseHandle함수를 이용한다.

– BOOL ReleaseMutex( HANDLE hMutex );

• 뮤텍스 소유를 해제한다.

3. 동기화

Page 17: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

33

#include <windows.h>#include "resource.h"

BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow){

DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ;return TRUE;

}

BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){

static HWND hEdit1,hEdit2;static HANDLE hFileMapping;static char * pMapView;static HANDLE hMutex;switch (message){case WM_INITDIALOG :

hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,1042,"MappingMutexSample");pMapView = (char *)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,0,0,1024);hEdit1 = GetDlgItem(hDlg,IDC_EDIT1);hEdit2 = GetDlgItem(hDlg,IDC_EDIT2);hMutex = CreateMutex(NULL,FALSE,"MyMutexSample");return TRUE ;

34

case WM_COMMAND :switch (LOWORD (wParam)){case IDC_BUTTON1:

{WaitForSingleObject(hMutex,INFINITE);char temp[256];GetWindowText(hEdit1,temp,256);SetWindowText(hEdit2,temp);strcpy(pMapView,temp);ReleaseMutex(hMutex);

}return TRUE;

case IDC_BUTTON2:{

WaitForSingleObject(hMutex,INFINITE);SetWindowText(hEdit2,pMapView);ReleaseMutex(hMutex);

}return TRUE;

case IDOK :case IDCANCEL :

EndDialog (hDlg, 0) ;return TRUE ;

}break ;}return FALSE ;

}

Page 18: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

35

• 이벤트– 어떤 사건이 일어났음을 알려주는 동기화 객체이다.

– 크리티컬 섹션, 뮤텍스, 세마포어는 주로 공유 자원을 보호하기 위해 사용되는 데 비해 이벤트는 그보다는 스레드간의 작업 순서나시기를 조정하기 위해 사용한다.

– 자동 리셋

• 대기 상태가 종료되면 자동으로 비신호상태가 된다.

– 수동 리셋

• 스레드가 비신호상태로 만들어 줄 때까지 신호상태를 유지한다.

3. 동기화

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName

);

36

• bManualReset : 이 이벤트가 수동 리셋 이벤트인지 자동 리셋 이벤트인지를 지정한다.

– TRUE : 수종 리셋 이벤트, FALSE : 자동 리셋 이벤트

• bInitialState : 이벤트 생성과 동시에 신호상태로 만들어 이벤트를 기다리는 스레드가 곧바로 실행하도록 한다.

– BOOL SetEvent( HANDLE hEvent );

– BOOL ResetEvent( HANDLE hEvent );

– BOOL PulseEvent(HANDLE hEvent );

3. 동기화

Page 19: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

37

#include <windows.h>#include "resource.h"#include <process.h>BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow){

DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ;return TRUE;

}typedef struct param{

HWND hEdit2;BOOL bCont;HANDLE hEvent;char * pView;

}PARAM;unsigned __stdcall MyThreadProc( void * pArguments ){

PARAM * pParam = (PARAM *)pArguments;while(pParam->bCont){

WaitForSingleObject(pParam->hEvent,INFINITE);SetWindowText(pParam->hEdit2,pParam->pView);

}_endthreadex( 0 );return 0;

} BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){

static HWND hEdit1,hEdit2;static HANDLE hFileMapping;static char * pMapView;static HANDLE hMutex;static HANDLE hThread;

38

static PARAM param;static HANDLE hEvent;switch (message){case WM_INITDIALOG :hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,1042,"MappingMutexSample");

pMapView = (char *)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,0,0,1024);hEdit1 = GetDlgItem(hDlg,IDC_EDIT1);hEdit2 = GetDlgItem(hDlg,IDC_EDIT2);hMutex = CreateMutex(NULL,FALSE,"MyMutexSample");hEvent = CreateEvent(NULL,TRUE,FALSE,"MyMutexSampleEvent");param.bCont = TRUE;param.hEdit2 = hEdit2;param.hEvent = hEvent;param.pView = pMapView;hThread = (HANDLE)_beginthreadex(NULL,NULL,MyThreadProc,&param,NULL,NULL);return TRUE ;

case WM_COMMAND :switch (LOWORD (wParam)){case IDC_BUTTON1:

{WaitForSingleObject(hMutex,INFINITE);char temp[256];GetWindowText(hEdit1,temp,256);strcpy(pMapView,temp);PulseEvent(hEvent);ReleaseMutex(hMutex);

}return TRUE;

case IDOK :case IDCANCEL :

EndDialog (hDlg, 0) ;return TRUE ;

}break ;}return FALSE ;

}

Page 20: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

39

스레드의스레드의 동기화동기화 정리정리

Thread의 sync 방법

- 일반적으로 thread는 자신을 sleep 상태로 만들어 다른thread와 sync조정

. thread가 sleep 상태로 되면 더 이상 schedule 되지 않음

. 자신을 sleep 상태로 만들기 전에 “special event”가 일어나면 깨우기를 요청함

. 요구한 상태가 발생하면 OS는 CPU를 할당하여, 그 스레드를 깨우고 scheduling 한다.

40

크리티컬크리티컬 섹션섹션(Critical Section)(Critical Section)

같은 크리티컬 섹션을 가지고 있는 스레드 중에 한 개의 스레드만 작업할 수 있게 해줌. (단점, 단일 프로세스 내에서만 사용 가능)

CriticalSection 이용

Page 21: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

41

뮤텍스뮤텍스((MutexMutex))

커널커널 객체로서객체로서 MultualMultual ExclusionExclusion의의 약자약자

multiple processmultiple process내의내의 threadthread들들 간에간에 사용사용 가능가능

프로세스간프로세스간 동기화동기화 가능가능..

크리티컬크리티컬 섹션과섹션과 유사유사 –– 여러여러 개의개의 스레드가스레드가 한한 개의개의 뮤텍뮤텍

스를스를 공유하고공유하고, , 이것을이것을 가지고가지고 있는있는 한한 개의개의 스레드스레드만만 작업작업..

크리티컬크리티컬 섹션은섹션은 여러여러 프로세스가프로세스가 동시에동시에 접근하는접근하는 DLL DLL 과과같은같은 파일에서는파일에서는 사용사용 불가불가..

MutextMutext 이용이용

42

세머포어세머포어(Semaphore)(Semaphore)

크리티컬 섹션, 뮤텍스 오직 한 개의 스레드만 동작

다수의 원하는 개수의 스레드 만큼 동시에 작업할수 있도록 함.

Semaphore 이용

리소스의 사용 카운트 수를 물어볼 수 있도록 함.

생성시 스레드의 번호와 최대 허용 가능한 스레드의 개수를 정의 함.

Page 22: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

43

세머포어세머포어 예제예제 설명설명

세마포어는 제한된 일정 개수를 가지는 자원(하드웨어, 윈도우, 프로세스, 스레드 등)을 보호 관리

자원의 개수를 카운트하는 동기화 객체와 실행가능한 스레드의 개수를 관리

동시 3개까지만 다운로드 가능한 프로그램

이 경우 자원이란 다운로드 권한

스레드에서는 WaitForSingleObject 함수를 호출하여 자신에게 권한이있는지 검사

가능하다면 다운로드 루프로 진입. 이때 대기 함수는 세마포어의 카운트를 1 감소

두번째, 세번째 스레드가 다운로드를 시작하면 세마포어의 카운트는 0비신호상태

첫번째 스레드가 다운로드를 완료하면 세마포어를 품. 다시 세마포어는 1증가. 신호상태, 대기중 스레드가 즉시 다운로드 시작

44

이벤트이벤트(Event)(Event)

동기화 개체 중 가장 기본적인 형태

크리티컬 섹션, 뮤텍스, 세머포어는 데이터 접근을제어하기 위해 사용

이벤트는 어떤 동작이 완료되었음에 대한 시그널사용

Event 이용

Manual-reset 이벤트 및 Auto-reset 이벤트 사용가능. 각각 동작 완료를 기다리는 스레드 모두(수동-리셍 이벤트) 또는 하나에게만(자동-리셋 이벤트) 시그널.

한 스레드가 초기화 하고, 작업 완료 후 다른 스레드에게 나머지 작업을 시작하라고 알릴 때 사용.

Page 23: 15. 가상메모리, 프로세스cfs6.blog.daum.net/upload_control/download.blog?fhandle=MEhhSnl… · •이함수가호출되면프로세스는정리작업에들어가즉각종료된다.

45

이벤트이벤트 예제예제 설명설명

쓰레드간의 작업 순서나 시기를 조정하고 신호를 보내기 위해 이벤트 사용

대기 스레드가 있을때, 스레드의 실행을 이벤트로 제어하고 쓰레드간 통신을 위해 이벤트 동기화 객체 사용

자동 리셋 이벤트(자동 비신호상태 변환)<-> 수동 리셋 이벤트(신호상태유지)

대기함수를 사용하지 않고도 임의적으로 신호상태/비신호 상태 설정

SetEvent(), ResetEvent()

30번까지 만 계산 후 화면 출력하는 프로그램

쓰레드의 진가는 백그라운드 작업시, 주 스레드의 블록방지 효과가 있음

그러나 화면 출력 등의 주 쓰레드와 관련이 있다면 스레드의 계산완료시 까지 기다리기 위해 블록 상태가 됨

화면에 출력될 분량만큼만 계산이 완료되면 주 스레드는 즉시 화면 출력 작업 시행

이를 위하여 작업 스레드가 어디까지 계산했는지 주 스레드에게 이벤트로 알림

46

사용할사용할 동기화동기화 클래스클래스 선택선택 요령요령

프로그램이 어떤 리소스에 접근하기 위해서 다른일이 발생하기를 기다릴 필요가 있는가 ?

Event 사용

동시에 여러 개의 클래스가 한 개의 리소스에 접근할 필요가 있는가 ?

Semaphore 사용

한 개 이상의 프로그램이 리소스에 접근하는가 ?

Mutext 사용