Thread를 위한 준비... 우선 OS가 제공하는 API에 대해 알아보자.
HANDLE CreateThread(.... )
말 그대로 Thread를 생성하는 API다. C/C++ Runtime으로 개발하는 개발자 기준이 아닌 윈도우즈
개발자 기준으로
본 설명을 이어나갈 것이다. ( 참고적으로 CreateThread 함수를 대체할 C/C++ Runtime 함수는
_beginthreadex 함수다 )
위의 CreateThread 함수가 호출되면 시스템은 Thread Kernerl Object를 생성하게 되는데, 이 Object는
OS가 Thread를 다루게 될 단순한 데이터 구조체이다. 이 과정이 끝나면 OS는 이 Thread가 사용할 Stack을
할당하고, 이 Thread는 이 Thread를 실행시킨 Process의 Context 내에서 실행되므로, 본 Process에 대한
모든 Kernerl Object Handle과 Memory, 또다른 Thread의 Stack에 까지도 접근할 수가 있다.
잠시 위에서 언급한 Process의 Context에 대해 부연 설명을 하자면, Process의 Context는
OS의 스케쥴러에 의해 시작될 Process와 그 환경에 대한 정보 집합을 의미한다. 이 정보 집합은
정적변수와 동적변수를 사용하는 실행코드와 스택, 레지스터, 프로그램 카운터를 포함한다.
이제 위의 CreateThread 함수에 대한 각 파라미터에 대해 알아보자.
HANDLE WINAPI CreateThread( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,1. LPSECURITY_ATTRIBUTES lpThreadAttributes: 구조체 포인터이며, Thread Kernerl Object에
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId);
대해 기본 보안 특성을 사용할 것이면 NULL을, Child Process로
이 Thread Kernerl Object Handle을 상속할 것이면 이 구조체의
bInhertHandle 멤버 변수를 TRUE로 설정하고, 이 구조체의 포인터를 Input
파라미터로 전달하면 된다.
이 구조체에 대해 자세히 알고 싶으면 아래를 보라.
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; // 이 Structure의 크기다
LPVOID lpSecurityDescriptor; // 공유 제어에 대한 보안 descriptor 포인터이다.
BOOL bInheritHandle; // Child Process로 Kernerl Object Handle을 넘겨줄건지
// 여부에 대해서..
} SECURITY_ATTRIBUTES,
*PSECURITY_ATTRIBUTES,
*LPSECURITY_ATTRIBUTES;
2. SIZE_T dwStackSize : Thread가 자신의 Stack에 대한 크기를 얼마로 할지 정한다. 모든 Thread는 자신만의
Stack 영역을 갖기 때문이다. CreateProcess를 통하여 시작되는 Primary Thread는
CreateProcess가 실행하는 실행파일내에 설정되어 있는 Stack의 크기로 Thread의
Stack 크기를 결정하게 된다. 참고로 실행파일의 Stack 크기를 변경하려면
Link 옵션에서 /STACK:[reserve][.commit] 으로 정하면 되는데 reserve의
Default값은 1Mb이다.
설명이 어려웠는데 0으로 설정하면 /STACK 링커 스위치를 이용하여 실행파일내에 있는
물리적 저장소의 초기 크기를 따른다. 나는 이게 편하다.
3. LPTHREAD_START_ROUTINE lpStartAddress : Thread가 수행할 함수의 포인터다. 이 함수의 입력 파라미터는
아래 설명하게될 CreateThread 함수의 4번째 인자가 된다.
4. LPVOID lpParameter : 위의 3.의 Thread에서 실행할 함수의 인자값이다.
5 . DWORD dwCreationFlags : Thread가 생성될 때 OS가 제어할 추가적인 플래그이다. 이 값이 0이면 Thread는
생성즉시 CPU에 의해 스케쥴링 된다. (난 주로 0으로 설정하고 사용한다. )
반대로 CREATE_SUSPENDED 플래그를 설정하면 Thread를 생성하고 초기화 완료된후
CPU에 의해 자동으로 스케쥴링 되지 않고 정지 상태가 된다.
6. LPDWORD lpThreadId : 새롭게 생성된 본 Thread의 ID를 얻을 DWORD형 포인터이다. 이 ID로 새로 생성된
Thread를 관리할 수 있게 된다.