스레드 생성과 종료

Server/Winodw Network 2015. 10. 6. 11:55

스레드 생성과 종료

 

윈도우  API에서 스레드를 사용하려면 CreateThread() 함수를 사용해야 한다.

 

 

성공 : 스레드 핸들 리턴, 실패 : NULL

 

 

lpThreadAttributes

- SECURITY_ATtRIBUTES 구조체 변수의 주소값을 대입한다.

- 대부분의 경우 NULL을 사용한다.

 

dwStackSize

- 새로 생성할 스레드에 할당되는 스택 크기

- 0을 사용하면 디폴트로 1MB가 할당된다.

 

lpStartSize

- 스레드 함수의 시작주소이다.

 

lpParameter

- 스레드 함수에 전달할 인자

- void형 포인터이므로 32비트 크기의 값 하나만 전달할 수 있다.

- 32비트보다 큰 값을 전달할 때는 구조체 변수에 값을 넣고 이 구조체의 주소값을

  전달하면 된다.

- 전달할 인자가 없으면 NULL을 사용한다.

 

dwCreationFlags

- 스레드 생성을 제어하는 값, 0또는 CREATE_SUSPENDED를 사용한다.

- 0을 사용하면 스레드 생성 후 곧바로 실행된다.

- CREATE_SUSPENDED 사용하면 스레드 생성은 되지만 ResumeThread() 함수를

   호출하기 전까지는 실행되지 않는다.

 

lpThreadId

- DWORD형 변수 주소값으로, 이 변수에 스레드ID가 저장된다.

- 스레드ID 필요하지 않다면 NULL을 사용한다.

 

 

 

윈도우에서 스레드를 종료하는 방법

1. 스레드 함수가 리턴

2. 스레드 함수 내에서 ExitThread() 함수를 호출

3. TerminateThread() 함수를 호출한다.

4. 주 스레드가 종료하면 모든 스레드가 종료된다.

 

 

C/C++ 라이브러리 함수를 사용하는 애플리케이션에서는 CreateThread(), ExitThread() 함수보다는  _beginthreadex(), _endthreadex() 함수를 사용하는 것이 좋다.

 

beginthread(), beginthreadex 원형

 

 

_StaratAdress

- 쓰레드를 시작할 함수의 포인터를 받는다.

_StackSize

- 쓰레드에 할당될 스택의 크기

_ArgList

- 첫번째  인자인 쓰레드가 시작할 함수에 인자로 넣어줄 void*이다.

 

_beginthread 쓰레드의 시작 함수 원형은

void ThreadFunc( void *arglist ); 이다.

 

benginthread의 경우에는 스레드가 생성된 후에 곧바로 스레드가 시작된다.

 

_Security

- 보안과 관련된 것, NULL 사용한다.

 

_InitFlag

- 0또는 CREATE_SUSPENDED 를 받는다.

- 0이라면 쓰레드가 생성될 때, 쓰레드를 곧바로 시작한다.

- CREATE_SUSPENDED라면 나중에 스레드를 시작하고 싶을 때에 ResumeThread()를 이용해서

  시작할 수 있다.

 

_ThrAddr

- 생성된 스레드의 ID를 반환한다.

beginthreadex 스레드의 시작 함수 원형

unsigned int _ _ stdcall ThreadFunc( void *arglist );

 

 

 

** 주의점

_ _stdcall 은  _ _cdecl과 같은 호출규약이다.

beginthreadex() 에서는 _ _ stdcall이라는 함수 호출 규약에 따라서 스레드 시작 함수를 인자로 받는다.  _ _cdecl은 c, c++ 기본 함수 호출 규약이라서 따로 명시하지 않아도 되지만

_ _stdcall 은 명시해줘야만 한다.

 

 

CreateThread()와 _beginthreadex() 의 차이점

- CreateThread() 함수로 만들어진 스레드에서 C 라이브러리 함수를 사용하면

  스레드가 종료될 때 메모리 누수가 일어나서 beginthreadex()를 쓰는 것이 좋다.

 

 

WaitForSingleObject()와 WaitForMultipleObjects()

 

특정 스레드가 종료할 때까지 대기할 수 있다.

 

hHandle

- 종료를 기다릴 스레드를 가리킬 핸들이다.

 

dwMilliseconds

- 대기 시간으로 밀리초 단위를 사용한다.

- 이 시간내에 종료하지 않더라도 WaitForSingleObject() 함수는 리턴한다.

   이때 리턴값은 WAIT_TIMEOUT이 된다.

- 스레드가 종료한 경우에는 WAIT_OBJECT_0이 리턴된다.

- 대기시간으로 INFINITE 사용하면 스레드 종료할 때까지 무한대기한다.

 

성공 시 : WAIT_OBJECT_0 ~ WAIT_OBJECT_0 + nCount-1 또는 WIAT_TIMEOUT

실패 시 : WAIT_FAILED

 

여러개의 스레드가 종료되기를 기다리려면 WaitForMultipleObjects() 함수를 사용해서

한번의 호출로 끝낼 수 있다.

 

nCount

- 이 함수를 사용하려면 스레드 핸들을 모두 배열에 저장해야한다.

- nCount는 배열 원소 개수이다.

- 최대값은 MAXIMUM_WAIT_OBJECTS(=64) 이다.

 

lpHandles

- 배열의 시작 주소를 나타낸다.

 

bWaitAll

- TRUE이면 모든 스레드가 종료할 때까지 대기한다.

- FALSE이면 한 스레드가 종료하는 즉시 리턴한다.

 

dwMilliseconds

- WaitForSingleObject() 의 인자와 동일

 

 

** 주의점

WaitForSingleObject()와 WaitForMultipleObjects() 두 함수는 스레드 종료 대기를 위한 전용 함수가 아니다.  

이 두 함수는 스레드의 동기화 목적으로 자주 쓰이는 함수이다.

 

 

실행 중지, 재실행

 

SuspendThread() 함수는 스레드 실행을 일시 중지하고,

ResumeThread() 함수는 스레드를 재실행한다.

 

운영체제는 스레드의 중지 횟수(suspend count)를 유지하면서 SuspendThread() 함수를 호출할때마다 +1 증가하고 ResumeThread()를 호출할 때마다 -1식 감소한다.

 

중지 횟수가 0보다 크면 스레드의 실행이 중지된다.

 

DWORD SuspendThread( HANDLE hThread );

성공시 : 중지 횟수 ,  실패 시 : -1

 

DWORD ResumeThread( HANDLE hThread );

성공시 : 중지 횟수 , 실패 시 : -1

 

스레드가 대기한다는 것은 CPU시간을 사용하지 않고 기다린다는 뜻이다.

루프를 돌면서 기다리는 방법보다 더 효율적이다.

  

 

 

'Server > Winodw Network' 카테고리의 다른 글

스레드의 우선순위 컨트롤  (0) 2015.10.12
프로세스, 스레드의 우선순위  (0) 2015.10.08
프로세스와 스레드  (0) 2015.10.05
로그 기록  (0) 2015.09.23
select 모델  (0) 2015.08.11
admin