WinMain과 메시지 루프, WndProc, 일반 함수들을 오가며 메시지를 처리하는 일련의 코드들을 스레드 라고한다.

프로세스는 단지 존재하기만 하는 껍데기일 뿐, 실제 작업은 스레드가 담당한다. 프로세스 생성시 하나의 주 스레드가 생성되며 대부분의 경우 주 스레드가 모든 작업을 처리하고 주 스레드가 종료되면 프로세스도 같이 종료된다.
주스레드 = 프로세스


그리고 주스레드 실행도중에 다른 작업을 같이 하고싶으면 스레드를 여러개 더 추가 할 수 있는데 그 스레드들을 실행하는 도중에 주스레드가 종료되면 실행중인 보조 스레드들도 다 종료된다.


스레드생성

HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)


LPSECURITY_ATTRIBUTES lpThreadAttributes - 스레드의 보안 속성을 지정하는데 자식 프로세스로 핸들을 상속하지 않는 한 NULL로 지정하면 된다.

DWORD dwStackSize - 스레드의 스택 크기를 지정하는데 스레드끼리 상호 안정된 동작을 하기 위해 스레드별로 별도의 스택이 할당된다. 스택의 초기 크기를 0으로 지정하면 주 스레드(Create Thread를 호출한 스레드) 와 같은 크기를 가진다. (기본적으로 스레드의 스택은 1M가 예약되며 프로세스의 주소 공간은 2G이므로 생성 가능한 스레드 개수는 약 2000개이다.)

LPTHREAD_START_ROUTINE lpStartAddress -  스레드의 시작 함수를 지정 

스레드 시작함수의 원형 - DWORD WINAPI ThreadFunc(LPVOID lpParameter)

LPVOID lpParameter - 시작 함수로 전달할 작업내용이다. 없을 경우 NULL

DWORD dwCreationFlags - 생성할 스레드의 특성을 지정하는데 0이면 물론 아무 특성 없는 보통 스레드이다. CREATE_SUSPENDED 플래그를 지정하면 스레드를 만들기만 하고 실행은 하지 않는다. 중지된 스레드를 실행 할때는 Resume Thread 함수를 호출한다.

LPDWORD lpThreadId - 스레드를 만든 후 스레드의 ID를 리턴하기위한 출력용 인수로이므로 DWORD형의 변수를 하나 선언한 후 그 변수의 번지를 넘기면 된다. 스레드 ID가 필요한 경우는 별로 없는데 이 경우는 NULL을 전달한다.

CreateThread 함수는 스레드를 만든 후 스레드의 핸들을 리턴하며 에러가 발생했을 경우 NULL을 리턴한다. 리턴된 스레드의 핸들은 이후 이 스레드를 제어하고자 할 때 사용하는데 생성 후 스레드를 더 이상 조작하지 않을 경우 곧바로 핸들을 닫아도 된다. 스레드 핸들과 스레드 자체는 다르므로 핸들을 닫는다고 해서 스레드가 종료되는 것은 아니다. 여섯 번째 인수로 스레드 ID도 리턴 되는데 핸들과 ID의 차이에 대해서 아래에 간략히 적어보겠다.



핸들 - 프로세스 내에서 해당 객체를 액세스할 때 사용하는 한정적인 값이며 이 핸들을 사용하여 객체를 마음대로 조작할 수 있다. (C++의 지역변수)
ID -  시스템 전역적인 값이며 다른 프로세스 ID와 절대 중복되지 않는다. 그래서 프로세스끼리 ID를 전달함으로써 목적이 되는 프로세스 핸들을 다시 오픈할 수 있다. 실행 중인 프로세스의 ID는 작업 관리자에서 쉽게 확인할 수 있다.
(C++에서 Get 함수)

정리 - 프로세스 ID는 프로세스간의 구분을 위한 중복되지 않는 식별값일 뿐이며 ID로부터 직접 프로세스를 제어할 수는 없다. ID로부터 핸들을 발급받아야만 비로소 이 객체를 제어할 수 있다.


스레드종료

자식 쓰레드가 작업을 할 때 주 쓰레드는 자식 쓰레드를 만들기만 하고 종료 상태에는 별로 관심을 두지 않는 것이 보통이다. 특별한 경우를 제외하고 두 쓰레드는 서로 독립적으로 실행될 뿐이다. 그러나 주 쓰레드는 적어도 자식 쓰레드가 종료되었는지의 여부는 주기적으로 조사해 봐야 한다. 이때 사용되는 함수가 GetExitCodeThread 함수이다.

 

BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);

 

hThread

쓰레드의 핸들 값

lpExitCode

쓰레드의 종료 코드조사를 위한 인수

 

 

때로는 작업 중간에 쓰레드를 종료해야 하는 경우가 있다. 예를 들어 다운로드를 받는 스레드를 만들었는데 중간에 사용자가 다운로드를 취소했다면 더 이상 이 쓰레드는 존재할 필요가 없다. 

쓰레드를 강제 종료할 때 사용되는 함수는 ExitThread 이다.

 

VOID ExitThread (DWORD dwExitCode);

ExitThread 는 쓰레드가 스스로 종료할 때 사용하는데 인수로 종료 코드를 넘겨준다. 쓰레드가 ExitThread 를 호출하면 자신의 스택을 해제하고 연결된 DLL을 모두 분리 후 파괴된다.

TerminateThread는 쓰레드 핸들을 인수로 전달받아 해당 쓰레드를 강제로 종료한다.

 





'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

WNDCLASS 구조체  (0) 2010.01.25
스레드의 함정  (0) 2010.01.25
이벤트  (0) 2010.01.24
세마포어  (0) 2010.01.24
파일매핑 사용순서  (0) 2010.01.24
Posted by 아몰라