350 likes | 660 Views
과목 : 윈도우즈 프로그램밍 특론. 메모리와 스레드. 발표자 : 권만준 지능자동화연구실 / 충북대학교 2004 년 05 월 04 일 화요일. 발표순서. 메모리 관리 - 가상 메모리 (Virual Memory) 개념 및 관련 함수 - GlobalAlloc 와 LocalAlloc 함수 - Heap 에 메모리 사용 함수 - 배열에 메모리 할당 new - 메모리 공유 기법 스레드 - 스레드 구동 방법
E N D
과목 : 윈도우즈 프로그램밍 특론 메모리와 스레드 발표자 : 권만준 지능자동화연구실/충북대학교 2004년 05월 04일 화요일
발표순서 • 메모리 관리 - 가상 메모리(Virual Memory) 개념 및 관련 함수 - GlobalAlloc와 LocalAlloc 함수 - Heap에 메모리 사용 함수 - 배열에 메모리 할당 new - 메모리 공유 기법 • 스레드 - 스레드 구동 방법 - 뮤텍스(Mutex), 세머포어(Semaphore), 이벤트(Event) - 멀티 스레드 예제 메모리와 스레드
가상메모리(Virtual Memory) ~ 메인 메모리와 함께 보조 기억 장치, 즉 보통 하드(HDD)라고 하는 곳의 일부분을 메모리로 사용하는 것. • 가상 메모리 관리자(VMM, Virtual Memory Manager) • 응용 프로그램이 사용하는 가상 메모리(Virtual Memory)를 실제 메모리(Physical Memory)로 변환해주는 역할을 담당 • Win32에서 각 응용 프로그램은 모두 4GB의 주소 공간을 할당 - 2GB의 메모리 공간을 사용할 수 있음 • 가상 메모리는 4KB(페이지) 씩으로 나뉘어 관리 - 실제 메모리는 크게 두 부분으로 구성된다. RAM과 스왑 파일(swap file)이라고도 하는 하드디스크 내의 페이징 파일로 구성 메모리와 스레드
메모리 구조 윈도우98 메모리 구조 4GB 3GB 2GB 4MB 0 Page Tables VxDs VMM System arena (Ring 0 shared) Linear Address System DLLs Memory-mapped Files Upper portion of Win16 global heap Shared arena (Ring 3 shared) Win32 code, data and resources (distinct linear to physical mapping for end process) Private arena (per process area) Lower portion of Win16 global heap MS-DOS DOS area 메모리와 스레드
가상 메모리 페이지 형태 • 사용(Committed) 페이지 • 실제 메모리에 할당된 페이지. 이 페이지만이 접근 가능. • 접근 제어 모드 - 접근 불가(No Access), 읽기 전용(Read Only), 읽기/쓰기 모드 • 예약(Reserved) 페이지 • 프로그램에 의해 할당은 되었지만 아직 쓰이지는 않고 있는 페이지 • 이 영역을 사용하려고 하면 페이지 폴트(page fault)가 일어나고, 그 페이지를 사용 페이지로 변환 • 자유(Free) 페이지 • 예약 페이지가 된 후 사용 페이지로 변환 메모리와 스레드
가상메모리 사용 방법 사용 방법 사용 예제 VirtualAlloc[메모리생성] LPVOID lpAddress; lpAddress = VirtualAlloc(NULL, 1024, MEM_RESERVE, PAGE_NOACCESS); BOOL vLock; vLock = VirtualLock(lpAddress, 1024); VirtualLock[페이지예약] 데이터를 페이지에 기록 메모리 사용 데이터를 사용함 VirtualUnlock[페이지예약취소] VirtualUnlock(lpAddress, 1024) VirtualFree[페이지없앰] VirtualFree(lpAddress, 1024, MEM_DECOMMIT); 메모리와 스레드
가상 메모리 함수 VirtualAlloc ~ 가상 메모리 영역을 예약(RESERVE)하거나 사용(COMMIT)하는데 사용 VirtualLock ~ VirtualAlloc에 의하여 할당된 메모리를 사용할 있도록 위탁을 받겠다는 의미 VirtualUnlock ~ 위탁을 해제 VirtualFree ~ VirtualAlloc으로 할당된 메모리 영역을 자유영역으로 만들고자 할 때 호출 VirtualProtect ~ 사용 페이지에 한하여 접근 제어 속성을 변경하는데 사용 VirtualQuery ~ 할당된 페이지들에 대한 정보를 얻어오는데 사용 메모리와 스레드
VirtualAlloc 함수 ▣ 가상 메모리 할당 LPVOID VirtualAlloc( LPVOID lpAddress, // 예약하거나 위탁받고 싶은 주소 DWORD dwSize, // 메모리 크기 DWORD flAllocationType, // 메모리 Allocation 형태 DWORD flProtect // 보호모드 설정 }; • 메모리 할당 형태 – flAllocationType MEM_COMMIT : 디스크가 메모리를 만들어 위탁. 만일 현재 위탁하여는 페이지가 이미 위탁받았다면 그때는 사용을 금함. MEM_RESERVE : 메모리를 예약. 기존에 사용하던 페이지를 그대로 예약한다는 의미. MEM_TOP_DOWN : 가장 최근에 맞게 메모리 만듦. • 보호모드 설정 – flProtect PAGE_READONLY : 읽기 전용으로 PAGE_READWRITE : 읽기 쓰기 전용으로 PAGE_NOACCESS : 다른 곳에서 사용을 할 수 없도록 접근 불가. 메모리와 스레드
VirtualLock, VirtualUnlock, VirtualFree 함수 ▣ 메모리를 어떤 변수에 위탁 BOOL VirtualLock ( LPVOID lpAddress, // 위탁을 받는 포인터 DWORD dwSize, // 위탁을 받는 메모리 크기 }; ▣ 위탁 해제 BOOL VirtualUnlock ( LPVOID lpAddress, // 위탁을 해제하는 포인터 DWORD dwSize, // 위탁을 해제하는 메모리 크기 }; ▣ 메모리 해제 BOOL VirtualFree ( LPVOID lpAddress, // 메모리 주소 포인터 DWORD dwSize, // 메모리 크기 DWORD dwFreeStyle // 해제하는 형태 }; • 해제 형태 – dwFreeStyle MEM_DECOMMIT : 예약만 취소 MEM_RELEASE : 완전히 메모리 삭제 메모리와 스레드
GlobalAlloc와 LocalAlloc 함수 ►GlobalAlloc : Global Heap 영역에 메모리 할당 LocalAlloc : Local Heap 영역에 메모리 할당 • 윈도95 이상에서는 차이 없이 가상 메모리 형태로 사용. • 즉, Heap 영역에 메모리 할당. ► VirtualAlloc와 GlobalAlloc, LocalAlloc의 차이점 VirtualAlloc은 64비트 메모리 주소 반환 GlobalAlloc과 LocalAlloc은 32비트 메모리 주소 반환 메모리와 스레드
GlobalAlloc 계열 함수 ▣ 메모리를 새로 만드는 함수 GLOBAL GlobalAlloc ( UINT uFlags, // 메모리에 적재 속성 DWORD dwBytes, // 적재할 메모리 크기 }; • 적재 속성 - uFlags GEM_MOVEABLE : 이동이 가능하게 메모리 만듦. GEM_DDESHARE : 두 갱의 프로그램에서 공유. ▣ 설정된 메모리 Lock ~ 현재 메모리를 움직이지 못하게 하고 내가 사용할 때 다른 곳에서 접근 및 수정 등을 할 수 없게 핸들을 내가 갖겠다는 뜻. LPVOID GlobalLock ( HGLOBAL hMem // 메모리 핸들 }; ▣ Lock 했던 메모리 해제 BOOL GlobalUnlock ( HGLOBAL hMem // 메모리 핸들 }; ▣ 메모리 해제 HGLOBAL GlobalFree ( HGLOBAL hMem // 메모리 핸들 }; 메모리와 스레드
GlobalAlloc 함수 사용 예제 LPSTR lpMem; // 만들 메모리 LPSTR lpHandle; // 메모리를 핸들링하는 함수 lpMem = GlobalAlloc( GMEM_MOVEABLE, 1024 ) ; // 메모리를 설정함. 메모리가 움직일 수 있도록 함. lpHandle = GlobalLock( (LPSTR)lpMem ); // 메모리를 예약함. // 메모리 사용 ………... GlobalUnlock( lpMem ); // 메모리의 예약을 해제함. GlobalFree( lpMem ); // 메모리의 메모리를 지움. 메모리와 스레드
Heap에 메모리 사용 함수 ▣ 상황 애니메이션이나 동영상을 사용하는 프로그램이 있다면 먼저 디스크 영역에서 데이터를 올려서 빠른 속도로 처리하여 화면에 출력해 주어야 함. • 해결책 : Heap 영역에 데이터 적재 메모리와 스레드
HEAP 관련 함수 ▣ 메모리를 새로 만드는 함수 HANDLE HeapCreate( DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize); ▣ HEAP을 메모리에 할당 LPVOID HeapAlloc( HANDLE hHeap, DWORD dwFlags, DWORD dwBytes ); ▣ HEAP 메모리의 영역 크기 변경 LPVOID HeapReAlloc( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, DWORD dwBytes ); ▣ HEAP 메모리의 크기 얻기 LPVOID HeapSize( HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem ); ▣ HEAP 메모리의 영역 해지 및 제거 BOOL HeapFree( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem ); BOOL HeapDestroy( HANDLE hHeap ); 메모리와 스레드
배열에 메모리 할당 new • C++의 동적 메모리 할당 방법 • new/delete 연산자 : 프로그램 실행 시에 동적으로 메모리를 할당하거나 반환함. • new연산자 : 원하는 타입의 객체를 생성하고 그에 대한 포인터를 반환 - 생성할 수 없으면 0을 반환 • delete연산자 : new로 생성된 객체에게 할당된 기억장소를 반환 ※ 클래스의 크기에 맞게 메모리를 할당 해 줌. 메모리와 스레드
new 예제 배열 생성 Int *data; data = new int[16]; .. delete [] data; 클래스 생성 CTestDlg *pDlg; pDlg = new CTestDlg; pDlg->DoModal(); delete pDlg; 메모리와 스레드
메모리 공유하기 • 메모리 공유(Sharing)또는 메모리 매핑(Mapping) ~ 하나의 메모리 파일을 만든 다음 이 메모리 파일을 두 개 이상의 모듈에서 공유하여 데이터를 서로 전달하고 받을 때 사용하는 방법. <개념> 메모리를 파일 처럼 오픈 하여 한쪽에서는 기록하고, 다른 한쪽에서는 읽는 방법으로 데이터를 공유하는 방법. 파일 = 메모리 • 메모리 공유를 위해 메모리 매핑 파일(Memory Mapping File)생성. 메모리와 스레드
메모리 공유하기 데이터를 기록하는 측의 프로그램 코드 HANDLE m_hMapping; LPVOID m_pViewOf; m_hMapping = CreateFileMapping ((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 10240, “ExMemMap” ); m_pViewOf = MapViewOfFile ( m_hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0 ); // m_pViewOf 포인터에 데이터를 기록 strcpy ((char *)m_pViewOf, “Text Data…” ); 데이터를 읽는 측의 프로그램 코드 HANDLE m_hMapping; LPVOID m_pViewOf; m_hMapping = OpenFileMapping ( FILE_MAP_READ | FILE_MAP_WRITE, FALSE, “ExMemMap” ); m_pViewOf = MapViewOfFile ( m_hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0 ); Cstring data = (LPSTR)m_pViewOf; // data에 “Text Data…”의 문자열이 설정됨. 메모리와 스레드
메모리 매핑 파일 관련 함수 ▣ 메모리 매핑 파일 생성 HANDLE CreateFileMapping ( HANDLE hFile, // 파일 매핑 핸들 LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 보안 속성 DWORD flProtect, // 읽기 쓰기 옵션 플래그 DWORD dwMaximumSizeHigh, // 상위 메모리 오프셋 최대 크기 DWORD dwMaximumSizeLow, // 하위 메모리 오프셋 최대 크기 LPCSTR lpName // 매핑 파일명 }; ▣ CreateFileMapping과 대응되는 함수 HANDLE OpenFileMapping ( DWORD dwDesiredAccess, // 접근 모드 BOOL bInheritHandle, // 기존 핸들 사용 LPCSTR lpName // 매핑 파일명 }; ▣ 공유할 메모리 페이지와 데이터를 기록할 포인터를 연결하는 함수 LPVOID MapViewOfFile ( HANDLE hFileMappingObject, // 매핑 파일 핸들 DWORD dwDesiredAccess, // 접근 모드 DWORD dwFileOffsetHigh, // 메모리 파일의 상위 오프셋 번지 DWORD dwFileOffsetLow, // 메모리 파일의 하위 오프셋 번지 DWORD dwNumberOfBytesToMap // 매핑하고자 하는 크기 }; 메모리와 스레드
[예제] 메모리 매핑 파일 처리 • 메모리 파일을 View와 대화 상자에서 공유 • View에서 수정된 데이터가 그대로 대화 상자에 반영 • 대화 상자는 모달리스 형식으로 운영 메모리와 스레드
[예제] 메모리 매핑 파일 처리 - 코드 메모리와 스레드
스레드란 ? • 스레드(Thread)란 하나의 작업 단위 • 독립적인 작업 단위 • 프로세스에서 실행되는 하나의 일관된 소스 코드 • 경량 프로세스( LWP : Light Weight Process ) <예> 워드 프로세서 작업 + 인터넷 다운로드 작업 프린터 도중에 문서 편집 작업 ? + 인터넷을 통한 데이터 다운로드 ? • 프린터 출력 스레드, 입력 작업 스레드 + 다운로드 스레드 멀티 스레드(Multi-Threaded) 메모리와 스레드
스레드의 구동 ① 스레드 프로그램 작성 ② 스레드 기동하기 - CMExThreadView에서 ThreadProc을 구동 ③ 스레드에 데이터 넘기기 - 전역 변수 이용 - lParam 이용 UINT ThreadProc ( LPVOID lParam ) // 사용자 정의 함수 { // 스레드의 작업 내용 코딩 } AfxBeginThread ( ThreadProc, this ); // WIN API 함수 UINT ThreadProc ( LPVOID lParam ) // 사용자 정의 함수 { CMExThreadView *pView = (CMExThreadView *)lParam; // 스레드 내용 코딩 } 메모리와 스레드
[예제] 스레드 프로그램 • SDI 형식의 프로그램 • 메뉴의 “스레드 시작”에 의해 스레드 시작 • 메뉴의 “스레드 종료”에 의해 스레드 중단 • 스레드 –화면에 랜덤한 크기의 상자를 임의의 색으로 그리는 스레드 메모리와 스레드
[예제] 스레드 프로그램 코드 메모리와 스레드
스레드의 동기화 • MFC에서 멀티스레딩을 위해 제공하는 클래스 - 동기 클래스 - CSyncObject, CSemaphore, CMutex, CCriticalSection, CEvent - 동기화된 접근을 허용 하는 클래스 – CMultiLock, CSingleLock • Thread의 sync 방법 - 일반적으로 thread는 자신을 sleep 상태로 만들어 다른 thread와 sync조정 . thread가 sleep 상태로 되면 더 이상 schedule 되지 않음 . 자신을 sleep 상태로 만들기 전에 “special event”가 일어나면 깨우기를 요청함 . 요구한 상태가 발생하면 OS는 CPU를 할당하여, 그 스레드를 깨우고 scheduling 한다. 메모리와 스레드
크리티컬 섹션(Critical Section) • 같은 크리티컬 섹션을 가지고 있는 스레드 중에 한 개의 스레드만 작업할 수 있게 해줌. (단점, 단일 프로세스 내에서만 사용 가능) • CCriticalSection클래스 이용 Thread1 Thread2 Thread3 Critical Section Thread 1이 critical section안에 있음 (critical section structure를 변경 중) Thread 2이 critical section에 도착 (Thread 1때문에 들어가지 못함 ) Thread 3 은 아직 critical section에 도착하지 못함 Critical Section Structure 메모리와 스레드
뮤텍스(Mutex) • 커널 객체로서 Multual Exclusion의 약자 • multiple process내의 thread들 간에 사용 가능 • 프로세스간 동기화 가능. • 크리티컬 섹션과 유사 –여러 개의 스레드가 한 개의 뮤텍스를 공유하고, 이것을 가지고 있는 한 개의 스레드만 작업. • 크리티컬 섹션은 여러 프로세서가 동시에 접근하는 DLL 과 같은 파일에서는 사용 불가. • CMutext클래스 이용 메모리와 스레드
세머포어(Semaphore) • 크리티컬 섹션, 뮤텍스 오직 한 개의 스레드만 동작 • 다수의 원하는 개수의 스레드 만큼 동시에 작업할 수 있도록 함. • CSemaphore클래스 이용 • 리소스의 사용 카운트 수를 물어볼 수 있도록 함. • 생성시 스레드의 번호와 최대 허용 가능한 스레드의 개수를 정의 함. 메모리와 스레드
이벤트(Event) • 동기화 개체 중 가장 기본적인 형태 • 크리티컬 섹션, 뮤텍스, 세머포어는 데이터 접근을 제어하기 위해 사용 • 이벤트는 어떤 동작이 완료되었음에 대한 시그널 사용 • CEvent클래스 이용 • Manual-reset 이벤트 및 Auto-reset 이벤트 사용 가능. 각각 동작 완료를 기다리는 스레드 모두(수동-리셍 이벤트) 또는 하나에게만(자동-리셋 이벤트) 시그널. • 한 스레드가 초기화 하고, 작업 완료 후 다른 스레드에게 나머지 작업을 시작하라고 알릴 때 사용. 메모리와 스레드
사용할 동기화 클래스 선택 요령 • 프로그램이 어떤 리소스에 접근하기 위해서 다른 일이 발생하기를 기다릴 필요가 있는가 ? CEvent 사용 • 동시에 여러 개의 클래스가 한 개의 리소스에 접근할 필요가 있는가 ? CSemaphore 사용 • 한 개 이상의 프로그램이 리소스에 접근하는가 ? CMutext 사용 메모리와 스레드
[예제] MultiThread • 두개의 스레드를 운영하는 방법 – Critical Section, Mutex 사용 예제 • MakeString : 문자열을 생성하는 스레드 • DisplayString : 생성된 문자열을 표시하는 스레드 메모리와 스레드
[예제] MultiThread - 코드 메모리와 스레드
[예제] MultiThread - 코드 메모리와 스레드
- The End - 메모리와 스레드