728x90

쓰레드 생성

windows에서 쓰레드 생성 함수는 CreateThread이다.

함수 선언

HANDLE CreateThread(

    LPSECURITY_ATTRIBUTES lpThreadAttributes,

   SIZE_T dwStackSize,

   LPTHREAD_START_ROUTINE lpStartAddress,

   LPVOID lpParameter,

   DWORD dwCreationFlags,

   LPDWORD lpThreadId

);

1.lpThreadAttributes : 핸들의 상속 여부 결정, NULL이 전달 되면 상속X

2.dwStackSize : 쓰레드의 스택 크기를 지정하기 위한 매개변수다.

                     0이 전달되면 디폴트 크기인 1M바이트가 적용된다.

3.lpStartAddress : 쓰레드의 main역할을 하는 함수를 지정하는 전달인자이다. 인자 타입이 LPTHREAD_START_ROUTINE                          인데 이는 다음과 같이 정의되어 있는 함수 포인터 이다.

typedef DWORD(WINAPI * PTHREAD_START_ROUTINE)

                     (LPVOID lpThreadParameter);

typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;

변환 타입이 DWORD이고 매개변수 타입은 LPVOID(void *)인 형태로 정의되어야 한다.

4.lpParameter : 쓰레드 함수에 전달할 인자를 지정하는 용도로 사용한다. main함수의 argv와 유사하다.

5.dwCreationFlags : 쓰레드의 생성 및 실행을 조절하기 위해 사용되는 전달인자다.

                          인자로 CREATE_SUSPENDED가 전달되면, 쓰레드는 생성과 동시에 Blocked상태에 놓이게 된다.                                 ResumeThread 함수가 호출되면 실행을 시작한다.

                           STACK_SIZE_PARAM_IS_A_RESERVATION을 전달할 경우 dwStackSize를 통해 전달되는 값의                                     크기는 reserve메모리 크기를 의미하게 되고, 그렇지 않을 경우 commit 메모리 크기를 의미하게                               된다.

6.lpThreadId : 쓰레드 ID를 전달받기 위한 변수의 주소값을 전달한다.

7.마지막으로 함수호출이 성공하면 생성된 쓰레드의 핸들이 반환된다.

 

생성할 수 있는 쓰레드의 최대 개수는 메모리가 허용하는 만큼이다. 쓰레드가 생성될 때마다 독립된 스택을 할당해 줘야만 한다. 그렇기 때문에 스택을 할당할 수 있을 때까지 쓰레드의 생성을 허용한다.

main 쓰레드의 return문은 프로세스의 종료를 의미하고 쓰레드 함수의 return문은 쓰레드 종료를 의미한다.

 

멀티 쓰레드 기반 프로그래밍에서 쓰레드의 흐름을 예측하는 것은 불가능 하다. 시스템의 당시 상황에 따라 다르게 동작하기 때문에 예측 자체가 의미가 없다.

 

스택은 쓰레드별로 독립적이기 때문에 쓰레드에 할당해주는 스택이 커질수록 쓰레드의 개수는 줄어든다.

 

Sleep함수

VOID Sleep(

          DWORD dwMilliseconds

);

1.dwMilliseconds : 쓰레드의 실행을 멈추기 위한 시간 정보를 Milliseond 단위로 지정한다. 0을 인자로 전달할 경우 자신에게 할당된 타임 슬라이스(Time Slice)를 포기하고 우선순위가 같은 다른 쓰레드에게 실행의 기회를 양보한다.

 

쓰레드 소멸

쓰레드 함수 내에서 return문을 통해 종료 및 소멸시키는 방법이 가장 이상적이다. 일반적으로 쓰레드 종료 방법에 있어서 return 이외의 방법은 거의 생각하지 않는다. 그러나 return외의 종료방법이 적절한 경우도 존재한다.

 

case 1 : 쓰레드 종료시 return 을 이용하면 좋은 경우

일반적인 경우에 return을 종료로 사용하는 것이 좋다. 특정한 연산의 결과값을 반환 할때도 return을 사용하는 것이 좋다. 쓰레드 함수가 반환한 결과값은 프로세스 종료코드 처럼 커널 오브젝트에 결과가 저장된다.

저장된 종료코드는 main쓰레드에서 GetExitCodeThread함수를 통해 가져올 수 있다.

BOOL GetExitCodeThread(

      HANDLE hThread,

      LPDWORD lpExitCode

);

1.hThread : 종료코드를 얻기 위한 쓰레드의 핸들을 인자로 전달한다.

2.lpExitCode : 얻게되는 종료코드를 저장할 메모리의 주소값을 전달한다.

 

case 2 : 쓰레드 종료 시 ExitThread 함수 호출이 유용한 경우(특정 위치에서 쓰레드의 실행을 종료시키고자 하는 경우)

ExitThread 함수가 존재한다. 이 함수는 현재 실행중인 쓰레드를 종료하고자 할 때 호출하는 함수로 return 방식의 쓰레드 종료만큼 선호된다.

VOID ExitThread(

      DWORD dwExitCode

);

dwExitCode : 커널 오브젝트에 등록되는 쓰레드 종료코드(Exit Code)를 지정

                  위 함수의 장점은 언제 어디서나 쓰레드를 종료시킬 수 있다는 점이다. 그렇다면 return 종료와 무엇이                        다른가.

 

예를 들어 C함수가 호출된 상태에서 쓰레드를 종료해야 한다면, ExitThread함수를 호출하는 것이 더 간결하다. return에 의한 종료를 원한다면 threadfunction까지 return을 해야만 종료가 가능해진다.

 

case 3 : 쓰레드 종료 시 TerminateThread 함수 호출이 유용한 경우(외부에서 쓰레드를 종료하고자 하는 경우)

main함수에서 쓰레드를 생성할 경우 해당 쓰레드의 핸들을 얻게된다. 이 핸들을 이용해서 쓰레드를 강제 종료시킬 수 있다. 순전히 외부에 의한 강제 종료이다.

BOOL TerminateThread(

     HANDLE hThread,

     DWORD dwExitCode

);

1.hThread : 강제 종료할 쓰레드 핸들.

2.dwExitCode : 종료할 쓰레드의 종료코드를 인자로 전달한다. 이 종료코드는 해당 쓰레드의 커널 오브젝트에 등록된다.

 

위 함수의 문제점은 강제 종료라는 점이다. 종료의 대상이 되는 쓰레드는 종료가 되는 시점까지도 자신이 종료된다는 것을 인식하지 못한다. 따라서 종료에 필요한 여러가지 일들(메모리 해제, 리소스 해제 등등)을 처리하지 못하고 종료된다.

728x90

'Programming > Windows System Programming' 카테고리의 다른 글

쓰레드 상태 컨트롤  (0) 2020.07.26
쓰레드의 성격과 특성  (0) 2020.07.25
쓰레드 구현 모델에 따른 구분  (0) 2020.07.22
쓰레드의 이해  (0) 2020.07.20
함수 호출 규약  (0) 2020.07.18

+ Recent posts