본문 바로가기

[+] Information/[-] System

Windows OS의 구조 및 원리 - 쓰레드

이전 글에서 프로세스에 대해 언급하고 간략하게나마 어떻게 구성되어 있는지 알아보았다. 이번에는 쓰레드라는 것에 대해서 알아 볼텐데 일단 쓰레드가 무엇인지 한번 알아보자.


쓰레드란, 실제 CPU에 의해서 명령어가 실행되는 주체를 말한다. 프로세스와 쓰레드의 관계는 지주와 소작농이라고 보면 된다. 프로세스는 자신 밑에 쓰레드를 두어 일을 시키고 쓰레드는 프로세스의 관리를 받으며 일을 한다. 프로세스는 EPROCESS 구조체를 이용해 메모리에서 구성된다고 하였는데 쓰레드는 ETHREAD 구조체를 이용해 그 구조가 형성 된다. 프로세스는 무조건 쓰레드 1개 이상을 가지고 있다. ETHREAD의 주요 멤버들은 다음과 같다.


 - struct _DISPATCHER_HEADER Header : 쓰레드의 종료와 관련된 동기화 객체이다.


 - unit32 ContextSwitches : Thread Switching 횟수


 - struct _LIST_ENTRY WaitBlock[4] : 쓰레드의 상태 중 대기 상태시 동기화 객체를 지시하는데 사용 되는 멤버이다.


 - byte KernelStackResident : 쓰레드의 Kernel Stack이 쓰레드 종료 후에도 Memory에 잔여하는지를 나타내는 멤버이다.


 - byte NextProcessor : 스케줄러에 의해 결정 된 다음 실행 CPU를 나타낸다.


 - struct _KTRAP_FRAME *TrapFrame : 예외 발생 시 사용 되는 Trap Frame 포인터이다.


 * 참고 : Trap Frame이란 에러가 발생하면 CPU는 Interrupt Routine을 수행하게 되는데 이때 수행 바로 직전에 사용 되던 레지스터 값들을 Strack 공간에 저장한다. 이를 Trap Frame이라 한다.


 - unit32 KernelTime : Kernel Mode에서 쓰레드가 수행 된 시간을 나타낸다.


 - unit32 UserTime : User Mode에서 쓰레드가 수행 된 시간을 나타낸다.


 - struct _LIST_ENTRY ThreadListEntry : 프로세스가 소유하고 있는 하위 쓰레드의 목록을 나타낸다.


 - struct _LIST_ENTRY PostBlockList : 쓰레드가 참조하는 모든 객체들의 목록을 나타낸다.


 - struct _LIST_ENTRY ActiveTimerListHead : 쓰레드에 활성화 된 Timer 목록을 나타낸다.


 - void *UniqueThread : 쓰레드의 고유 번호이다.


 - void *Win32StartAddress : User Level에서 생성 된 쓰레드의 시작 코드가 위치한 부분을 나타낸다.


프로그램에서 쓰레드의 정보(ETHREAD)를 얻으려면 어떻게 해야 할까? 프로세스와 마찬가지로 Windows Device Development Kit의 PsGetCurrentThread() 함수를 사용하면 된다. PsGetCurrentProcess() 함수와 별다를 바가 없다. 다른 프로세스의 쓰레드 정보를 얻고 싶다면 PsLookupThreadByThreadId() 함수를 사용하면 된다.


Windows에서 쓰레드는 프로세스와 다르게 목적이 있는 실행 코드 별로 쓰레드를 구분 할 수 있다. 쓰레드는 독립적인 요소로 Error Handling을 가지는데 Windows에서 이를 지원해주고 있다. 이러한 기능을 Structed Exception Handling 이라 한다.


쓰레드에 자세히 알고자 한다면 여기를 참고하기 바란다.