kihwaa

kihwaa.egloos.com

포토로그 마이가든



Collabox... article


CollaBox : 콜라 박스 가 아니라 collaboration Box 이다.. Box 즉 Device 이다..


목적성 : 고해상도를 가지고 있는 타일드 디스플레이에서 효과적인 인터랙션 수행하기 위한 도구

Tracking :  gyroscope, ultrasonic, vision (Marker)
Recognition : Speech, Handwrite
Display : Tiled Display ( 약 7000 * 3000 )

음.. 내 논문을 다운 받으려해도 돈을 내야 하니.. 어디있지.. 원본이..

base64


64진수를 베이스로 하여 정보를 표현한다.(컴퓨터는 2진수 기반)
따라서 최소비트 (64=2^6) 6 비트를 가진다.
하지만 컴퓨터는 기본이 되는 정보를 1 바이트(8 비트)를 사용하여 표현한다.
(2=2^1 1 비트이지만... ASCII 코드 1바이트 사용)

그래서 6 과 8의 최소공배수인 24 비트(3 바이트)를 기준으로 하여 정보를 표현한다.
24비트는 6비트씩 4개가 나오므로 base64로 인코딩된 값의 길이는 4의 배수이다.


위의 그림과 같이 값을 24비트에 걸쳐서 표현한다.
앞에서부터 6비트씩 짤라서 4개의 문자를 만든다.
여기에 심볼을 대입한다.

base64 심볼 : (ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=)

'A' = 0 , 'B' = 1, …… '/' = 63,

' = ' 이 심볼은 인코딩 하려는 데이터가 3바이트(24 비트) 로 나누어 떨어지지 않는 경우를 의미한다.

만약 'a' 를 입력했다면 1 바이트가 채워진다.
24 비트중에 앞에 8비트만 채워지므로
6비트로 나누어 보면 첫번째 6비트가 채워지므로 심볼하나가 나오고,

두번째 6비트중 앞에 2비트가 채워지므로 두번째 심볼이 나오지만
세번째 6비트부터는 입력된 데이터가 없다. 이럴때 세번째 심볼과 네번째 심볼은 ' = ' 이 된다.
따라서 최대 '='의 개수는 2개이다. (ex. **==)

base64 인코딩, 디코딩 예 :

인코딩(encoding) :

'A' 입력 -> 'A' 의 아스키값 : 65(Dec)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
0 1 0 0 0 0 0 1


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
0 1 0 0 0 0 0 1

첫번째 6비트 값 = 16 = 'Q'
두번째 6비트 값 = 16 = 'Q'
세번째 6비트 값 = ' = '
네번째 6비트 값 = ' = '


디코딩(decoding) :

'QQ==' 입력

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
0 1 0 0 0 0 0 1


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
0 1 0 0 0 0 0 1

첫번째 바이트 값 = 65 = 'A'

Memory Study

메모리 상태 :


페이지의 개수 = 가상 메모리의 크기 / 페이지 하나당 크기

페이지 개수는 가상 메모리의 크기에 비례하며(가상 메모리는 몇 비트 환경인지에 비례 (ex. 32비트 4GB)),

모든 페이지는 Reserve, Commit, Free 세가지 중 하나의 상태를 지닌다.

Commit : 물리 메모리에 할당된 상태

Reserve : Free 와 Commit 의 중간상태이다. 해당 번지에 대해 예약을 한다.
다른 메모리 함수가 물리 메모리에 해당 번지에 할당하지 못하도록 한다.
하지만 물리 메모리의 소비는 발생하지 않는다.

Free : 물리 메모리 할당이 이뤄지지 않은 상태


메모리 할당의 시작점과 단위 확인 :

가상 메모리 시스템은 페이지 단위로 관리된다.

페이지의 중간 위치에서부터 할당을 시작할수 없으며, 페이지 크기의 배수 단위로 할당한다.

Allocation Granularity Boundary : 메모리 할당의 시작 주소가 되는 기본 단위
(참고 : 메모리가 지나치게 조각나는것과 관리의 효율성을 이유로 페이지 크기의 배수보다 더 넓은 값을 가진다)

Allocation Granularity Boundary 과 페이지 크기 확인 :

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

int _tmain(int argc, TCHAR *argv[])
{
SYSTEM_INFO si;
DWORD allocGranularity;
DWORD pageSize;

GetSystemInfo(&si);
pageSize = si.dwPageSize;
allocGranularity = si.dwAllocationGranularity;

_tprintf(_T("Page Size : %u Kbyte \n"), pageSize/1024);
_tprintf(_T("Allocation granularity : %u Kbyte \n"), allocGranularity/1024);

return 0;
}



가상 메모리 컨트롤 :

페이지 상태를 RESERVE 나 COMMIT 로 변경할때 사용하는 함수

LPVOID VirtualAlloc(
LPVOID lpAddress, // 예약 및 할당하고자 하는 메모리의 시작 주소
// (일반적 NULL 전달, RESERVED -> COMMIT 일때 해당페이지 시작 주소 지정)
SIZE_T dwSize, // 할당하고자 하는 메모리의 크기를 바이트 단위로 지정
// 메모리의 할당은 페이지 크기 단위로 결정
DWORD flAllocationType, // 메모리 할당의 타입.
// RESERVE : MEM_MRESERVE, COMMIT : MEM_COMMIT
DWORD flProtect // 페이지별 접근방식에 제한을 두는 용도
// RESERVE 상태로 변경할때는 접근을 허용하지 않는 PAGE_NOACCESS ,
// COMMIT 상태로 변경할때는 읽고/쓰기 모드인 PAGE_READWRITE 전달
);

함수 호출이 성공하면 할당이 이뤄진 메모리의 시작 주소를 리턴


할당된 페이지를 되돌리는 함수

BOOL VirtualFree(
LPVOID lpAddress, // 해제할 메모리 공간의 시작 주소
SIZE_T dwSize, // 해제할 메모리 크기를 바이트 단위로 지정
DWORD dwFreeType // MEM_DECOMMIT : 해당 페이지의 상태를 RESERVE 상태로 되돌린다.
// MEM_RELEASE : 해당 페이지의 상태를 FREE 상태로 되돌린다.
// 두번째 전달인자 dwSize 는 반드시 0 이어야 한다.
);



힙 컨트롤 :

디폴트 힙(Default Heap) :

디폴트 힙을 구성하는 페이지들은 RESERVE 상태이다. 일부는 성능을 위해 COMMIT 상태일수도 있다.

C 언어의 malloc 함수와 free 함수, C++ 언어의 new와 delete 를 사용해서 힙영역을 사용할 경우

프로세스를 생성할때 생성되는 힙, 즉 1M 바이트 크기의 디폴트 힙에 메모리를 할당한다.
(COMMIT 와 RESERVE 상태를 오간다)

프로세스에 기본적으로 할당되는 힙이며 프로세스 힙(Process Heap)라고도 한다.


디폴트 힙 컨트롤 :

디폴트 힙의 기본 크기는 1MB 이다. 링커(Linker)옵션을 통해 크기를 변경할 수 있다.

/HEAP : reserve, commit (ex. /HEAP 0x200000, 0x10000 : 디폴트 힙의 크기 : 2MB, COMMIT 크기 : 64KB)

힙은 동적이라 기본 크기 1MB 로 생성이 된 후 필요에 따라 그 크기가 Windows 시스템에 의해 자동으로 늘어난다.



Windows 시스템 힙(Dynamic Heap) :

Windows 시스템 함수를 통해 여러 힙을 추가로 생성할 수 있다.

가상 메모리 범위 내에서 프로세스 생성시 만들어지는 디폴트 힙 이외에 필요로 하는 힙을 얼마든지 생성할 수 있다.


힙(Dynamic Heap) 생성이 가져다 주는 이점 :

1. 메모리 단편화의 최소화에 따른 성능 향상 :



2. 동기화 문제에서 자유로워짐으로 인한 성능 향상 :

힙은 쓰레드가 공유하는 메모리 영역이다. 따라서 둘 이상의 쓰레드가 동시접근 할때 문제가 발생할수 있으므로

Windows 내부적으로 동기화처리를 해준다.(여기서 동기화는 메모리 할당과 해제)

같은 주소 번지에 둘 이상의 쓰레드가 동시에 메모리를 할당 및 해제하는 상황이 발생할 경우 메모리 오류(Corrupt)가
발생하므로 디폴트 프로세스 힙은 동기화 처리를 하는데 쓰레드마다 독립된 힙을 가지고 있다면

이러한 동기화가 필요없으므로 성능이 향상된다.


힙(Dynamic Heap) 컨트롤 :

힙을 생성하는 함수 :

HANDLE HeapCreate(
DWORD flOptions, // 생성되는 힙의 특성을 부여 (0 을 전달시 가장 일반적인 힙 생성)
// HEAP_GENERATE_EXCEPTIONS : 오류 발생시 NULL이 아닌 예외 발생
// HEAP_NO_SERIALIZE : 생성된 힙의 메모리 할당과 해제에 대해
// 동기화 처리를 하지 않는다.
// 둘 이상의 속성을 비트 단위 연산자 OR( | )로 동시 지정 가능
SIZE_T dwInitialSize, // dwMaximumSize 에서 지정한 메모리 중에서
// 초기에 할당할 COMMIT 페이지를 지정한다
SIZE_T dwMaximumSize // 생성되는 힙의 크기 결정.
// 지정하는 크기에 해당하는 페이지의 수만큼 RESERVE 상태가 된다.
// 0이 아닐 경우 힙은 증가가능한 메모리(Growable Heap)가 된다
);

힙을 소멸하는 함수 :

BOOL HeapDestroy(
HANDLE hHeap // 반환하고자 하는 힙의 핸들
);

힙에 메모리를 할당하는 함수 :

LPVOID HeapAlloc(
HANDLE hHeap, // 메모리 할당이 이뤄질 힙의 핸들
DWORD dwFlags, // HEAP_GENERATE_EXCEPTIONS : 오류 발생시 NULL이 아닌 예외 발생
// HEAP_NO_SERIALIZE : 함수호출시 동기화 처리되지 않는다.
// (HeapCreate 함수호출에서 지정했다면 중복지정할 필요는 없다)
// HEAP_ZERO_MEMORY : 할당된 메모리는 0으로 초기화
// 둘 이상의 속성을 비트 단위 연산자 OR( | )로 동시 지정 가능
SIZE_T dwBytes // 할당하고자 하는 메모리의 크기를 지정
// (증가가능한 힙이 아닐 경우 최대 크기 0x7FFF8)
);

힙에 메모리를 해제하는 함수 :

BOOL HeapFree(
HANDLE hHeap, // 해제할 메모리를 담고 있는 힙을 지정
DWORD dwFlags, // HEAP_NO_SERIALIZE 가 인자로 올 수 있다, 일반적 : 0
// (HeapCreate 함수호출에서 지정했다면 중복지정할 필요는 없다)
LPVOID lpMem // 해제할 메모리의 시작 주소 지정
);

커널 오브젝트 Study

커널 오브젝트 : Windows 운영체제에서 리소스(Resource : 프로세스, 쓰레드, 파일)들을
관리하기 위한 데이터를 저장하는 메모리 블록



Windows에서 관리하는 리소스 특성을 변경하기 위해서는 해당 리소스의 커널 오브젝트를 조작해야한다.

해당 리소스의 정보를 저장하고 있는 커널 오브젝트에 접근하기 위해서는

커널 오브젝트들을 구별하는 커널 오브젝트 핸들(Object Handle)을 얻어야 한다.



커널 오브젝트와 핸들 :

커널 오브젝트는 Windows 운영체제에 종속적이다.

사용자가 리소스 생성을 요청하면 운영체제에서 사용자가 요청한 대로 리소스를 생성하게 되고

이를 관리하기 위해 커널 오브젝트를 생성한다.

즉, 커널 오브젝트는 Windows 운영체제에 의해 생성 및 소멸이 결정된다.


리소스가 생성되어 커널 오브젝트가 생성되면 커널 오브젝트에 핸들이 부여되고

부모 리소스도 구조체 변수를 통해 자식의 커널 오브젝트 핸들을 획득할 수 있다.

즉, 부모와 자식이 자식의 커널 오브젝트를 공유한다.


예)

부모 프로세스가 자식 프로세스의 커널 오브젝트 핸들 획득.

typedef struct _PROCESS_INFORMATION
{
HANDLE hProcess; // 커널 오브젝트 구분 위한 핸들
HANDLE hThread;
DWORD dwProcessId; // 프로세스 구분 위한 ID
DWORD dwThreadId;
} PROCESS_INFORMAION;

위 구조체는 CreateProcess 호출할때 인자로 전달되는 구조체이다.(&pi)
호출이 완료되면 이 구조체에 자식 프로세스의 커널 오브젝트 핸들값이 hProcess 에 저장된다.

자신의 커널 오브젝트 핸들 획득.

GetCurrentProcess()

위함수를 사용하면 자신의 커널 오브젝트 핸들값을 리턴한다.



커널 오브젝트와 Usage Count :

운영체제는 해당 커널 오브젝트를 참조하는 대상이 하나도 없을때 커널 오브젝트를 소멸시킨다.

참조하는 대상은 Usage Count(참조 횟수)로 관리한다.

즉, Usage Count = 0 일 때 커널 오브젝트를 소멸한다.

리소스의 생성과 동시에 해당 커널 오브젝트의 Usage Count = 1 이된다.
생성이 완료되면 부모가 자식 리소스 커널 오브젝트의 핸들을 획득하기에 Usage Count = 2 가 된다.

만약 자식 리소스를 소멸하면 Usage Count 가 하나 줄어든다.

여기서 문제가 발생한다. 리소스가 소멸됬음에도 그 리소스를 관리하는 커널 오브젝트는 소멸되지 않는다.
(Usage Count 가 1이므로)

Usage Count = 0 을 만들기 위해선

부모의 자식의 커널 오브젝트 참조를 해제해야 한다.

CloseHandle() 함수를 사용하면 자식의 커널 오브젝트 핸들을 반환하여 참조를 해제한다.

즉, Usage Count 가 하나 줄어든다.

따라서 커널 오브젝트를 소멸하기 위해서는

부모가 소유한 자식의 커널 오브젝트 핸들을 반환해야 한다.


예)

부모 프로세스가 자식의 커널 오브젝트 핸들을 반환하지 않아 커널 오브젝트가 소멸되지 않았다고 가정할때

계산기 프로세스를 생성하면 그에 따른 커널 오브젝트가 생성된다.

계산기 프로세스를 종료시켜도 커널 오브젝트는 소멸되지 않는다(Usage Count = 1이므로 )

실행-> 종료, 실행 -> 종료 를 반복한다고 할때

커널 오브젝트는 실행의 수만큼 존재한다.

따라서 이 문제를 해결하기 위해 CloseHandle 을 통해 부모의 자식의 커널 오브젝트 참조를 해제함으로써

자식 프로세스가 종료될때 Usage Count = 0 이 되어 커널 오브젝트가 소멸된다)


(참고 :

바탕화면에서 아이콘을 통해 프로세스를 생성할 경우에도 Usage Count = 2 다.

바탕화면 자체도 프로세스이기 때문이다. 이 때는 바탕화면이 부모 프로세스가 된다.
(Cmd 에서 실행하면 Cmd 가 부모 프로세스)

즉, 프로세스는 생성과 동시에 Usage Count = 2 가 된다)

Managed-Unmanaged callback C++/CLI

+++ Managed++

 

//! Delete 선언

private delegate void recvCommand(DotCALLBACKTYPE type);

private recvCommand recvFunctor;

//! Pin Ptr 생성

recvFunctor = Receive_DlgCommand;  

IntPtr callAddr = Marshal.GetFunctionPointerForDelegate(recvFunctor);

 

+++CLI+++

//! Native 연결

void Callbackadd(System::IntPtr^ ptr)

 {

      m_vaevent->SetCallback((CallbackType)ptr->ToPointer());

 }

 void CallbackRelease()

 {

      m_vaevent->RemoveCallback();

 }

 

+++Native+++

//! Funtion Pointer 생성

typedef int(__stdcall *CallbackType)(NATIVECALLBACKTYPE);

CallbackType _callback;

 

//! Callback 함수 선언

void SetCallback(CallbackType cb)

 {

  _callback = cb;

 }

 void RemoveCallback()

 {

  _callback = 0;

 }

 void DotCallback(NATIVECALLBACKTYPE _calltype)

 {

  assert(_callback != NULL && " Window handler _callback is null");

  _callback(_calltype);

 }

 

기존에 CLI에서 IntPtr을 생성하였을 경우 가비지 형이 메모리 정리정돈을 할때

청소를 하는 문제가 발생하는데.. 위 같이 Managed 에서 IntPtr을 생성하면 문제를

해결할수 있습돠~


1 2 3