4 min read

WIN api를 이용한 스레드 생성

예전에 적었던 포스트를 정리 차원으로 해당 글을 포스팅합니다.

예전 싱글코어인 시절에는 운영체계가 여러프로게스들이 실행되도록 스케줄링을 작업을 해주었지만 (이를 멀티프로세싱) 지금 시점으로 멀티코어가 당연시 되면서 운영체계에서 여러코어들에 대해 멀티테스킹은 물론이와 멀티스레딩도 동시에 실행하게 되었습니다.

좀더 간단히 이야기하면 하나의 작업을 동시에 실행시키겠다라는 말이 됩니다.

_beginthread함수도 있지만 이게 왜 만들어 졌는지에 대해 이야기하기전에 우선 CreateThread함수를 살펴보겠습니다.

msdn의 createthread 함수입니다. 요즘의 책들은 _beginthread를 쓰라고 하지만 _beginthread함수가 createthread 함수를 warp한거라 이거부터 설명하겠습니다.

lpThreadAttributes : 해당 보안설정은 프로세스간의 통신할떄 필요로 하는값입니다.

dwstarcksize : 새로 생성할 스레드에 활당되는 스택의 크기입니다. 0으로 설정되면 디폴트값으로 1MB정도 활당됩니다.

lpstartAddress : 스레드에서 시작할 함수의 시작 주소입니다. 단 . 함수의 원형은 꼭 이런식으로 설정해야합니다

lpParameter: 스레드에 전달시킬 포인터 값입니다.


dwcreationFlags : 쓰레드 생성이후 바로 실행 가능한 상태 혹은 대기 상태를 결정하는 옵션 입니다. 바로 시작은 0 이고 나머지는 MSDN에 찾아보기바랍니다.

lpthreadID : 스레드 생성시 스레드의 ID가 저장되는곳입니다. ID가 필요하지 않을경우 NULL로 지정해도 문제 없습니다.

함수의 인자는 위와 같이 설정되어있습니다.  샘플코드는 다음과 같습니다.

#include <stdio.h>
#include <Windows.h>
 
DWORD WINAPI dispay(LPVOID arg){
    int a = (int)arg;
    int i;
    for (i = 0; i < a; i++){
        printf("date : %d \n", i);
    }
    return 0;
}
int main(){
    int arr[2] = { 30, 9 };
 
    DWORD threadID;
    HANDLE thread1 = CreateThread(NULL, 0, dispay, (LPVOID)arr[0], 0, &threadID);
 
    WaitForSingleObject(thread1, INFINITE);
}

WaitForSingleObject의 함수는 해당 핸들이 시그널상태가 될때 까지 기달리는 함수입니다.  위와 같이 간단하게 짤수 있는것을 확인할수 있습니다. 하지만 이코드에는 문제가 많습니다. 

문제될만한 코드는 딱히 안보이겠지만 C함수를 쓸경우 문제가 발생가 발생하게됩니다. 예로 들면 strtok가 있겠습니다.  기존의 C함수들의 문제점은 반환을 전역변수를 반환 하게됩니다. 대충 아래와 같습니다. 

int error; // 전역변수
void fn(){

error = setErrorCode();
}

이와 같은식이면 다른 스레드가 error전역변수를 쓰기를 하여 원하지않은 에러코드 발생할수 있습니다. 그래서 등장한게 _beginthread 입니다.

_beginthread의 구현부분은 msdn에서 문서화하지는 않았지만 Windows Via C++에서는 구현부를 어느정도 정리해 두었습니다. 

간단히 설명하지만 thread를 생성시 독자적인 TLS를 만드는 행의를 하게됩니다. 결과적으로 서로다른 스레드가 다른 전역변수를 가르키게 되고 시스템에 약영향을 끼치는 영향이 사라집니다.

_beginthread에 사용법에 대해서는 다음 MSDN을 참조 하길 바랍니다. https://msdn.microsoft.com/ko-kr/library/kdzttdcb.aspx