Windows_/Windows32_API

Windows :: 윈도우즈 스레드(thread) 프로그래밍

sosal 2014. 7. 24. 10:16
반응형

/*

 * http://sosal.kr/

 * made by so_Sal

 */

 

 


동시에 원하는 일을 하기 위해서, 다중 프로세스를 이용하였습니다.
(다중프로세스와 스케쥴러에 대한 내용은 링크를 참조하세요 :: LINK_)
다중프로세스는 프로세스간의 자원을 공유하지 않고,
IPC라는 방법을 사용하여 통신을 해야 하기 때문에,
다중 프로세스 프로그래밍에서는
메모리 낭비, 컨텍스트 스위칭에 의한 속도 저하
단점이 많습니다.

위 문제점을 극복하기 위해서 스레드 기법을 사용하였습니다.
한 프로세스 내에 스택을 여러개 두어,
IPC처럼 메모리 공유가 필요 부분은 공유하는 구조를 만드는 것입니다.



한 프로세스 안에서 스택을 여러개 생성하여,
메모리 흐름을 여러개 만들어서 다중프로세스처럼
한 프로세스가 한번에 다양한 일을 수행하게 하는것입니다.

그렇다면, 위의 그림에 해당하는 스레드는 총 몇개일까요? 3개입니다.

1. Main thread. <스레드를 생성하지 않은 프로세스도 하나의 스레드를 가짐>
2. A thread.
3. B thread.

그림을 보시면 Stack은 공유하고 있지 않고,
Heap, Data, Code영역은 공유하고 있습니다.

결론.
스레드(thread)는 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위를 말한다.

Thread Stack의 독립적 할당


쓰레드를 생성할 때마다, 해당 쓰레드만을 위한 메모리 공간(Stack)을
Thread Stack이라 부르는데, 스택이 필요로 하는 동작을 위한
필요 공간을 따로 제공합니다.
그 외의 공간은 본래의 프로세스 메모리 영역을 공유합니다.
 :: 실행 흐름의 추가를 위한 독립적 메모리 영역



메모리를 공유?

Data, Heap, Code 영역의 공유!
다중프로세스 프로그래밍에서는 IPC를 이용하여 프로세스간의 통신을 구현했지만,
스레드끼리는 서로 DATA 영역, Heap 영역을 공유하고 있기 때문에
통신이란 의미가 무색합니다.
전역변수동적할당 된 메모리 공간은 서로 공유가 가능


프로세스는 CPU에 종속적이며,
CPU의 ALU 연산장치에 들어갈 Register Set 이 프로세스마다 각각 존재하여,
프로세스 객체들의 Context Switching (CPU에 올라갈 Register Set이 계속 바뀌는 현상)
에 이해 동시작업처럼 보이는 것임. 을 알고있습니다.
// 프로세스는 레지스터가 정보를 가리켜, CPU (특히 연산장치인 ALU)에 의해 계산, 실행되는데
// CPU는 단 하나이기 때문에 자신의 프로세스를 계산, 실행하고 있던 Register를 하나의 Set으로
// 저장해야합니다. CPU를 독점하고 있는 나의 Register Set이 따로 저장되어지고,
// 다른 프로세스의 차례가 오면, 다른 프로세스의 Register Set이 다시 CPU에 등록되게 되는데
// 이 과정을 Context Switching 이라 합니다.


프로세스 내부에서 실행되는 흐름의 단위는 스레드이고,
프로세스는 여러개의 스레드를 담는 하나의 테이블이라고 말할 수 있습니다.
// 크게, 프로세스끼리 Context Swtichig이 일어나고,
// 프로세스 내부적으로는 Thread context Switching이 일어납니다.


다중 프로세스의 경우

ALU에 들어갈 Register Set이 각각의 프로세스마다
모두 존재하게 됩니다.
따라서 프로세스간 Context Switching시에, Register Set이
서로 완전히 다르기 때문에 상당히 오랜 시간이 걸리게 됩니다.

하지만, 다중 스레드의 경우
Register Set을 switching 하는 과정에서
프로세스 내부적으로 Thread Stack을 제외한 모든 메모리 공간을 공유하기 때문에
스택에 관련된 몇개의 레지스터만 바꾸는 과정이 (ex fp, sp // frame pointer, stack pointer)
프로세스 Context Switching 과정을 대신합니다.

CPU의 입장에서 이경우는, Switching 되는 레지스터가
프로세스간 Context Switching보다 더 작기 때문에
다중 스레드를 이용할경우, 다중 프로세스보다 스위칭하는 속도가 조금 더 빠릅니다.
위 레지스터에 의한 속도 증가는 아주 일부분일뿐, (레지스터 메모리 크기가.. 겨우 몇바이트죠)
실제로 다중 프로세스보다 다중 스레드가 빠른 이유는 Cache 메모리에 있습니다.
캐쉬는 CPU에서 읽어들인 메인 메모리의 데이터를 임시적으로 저장하고 있다가
CPU가 다시 필요할때 다시 전달해주는 용도로 사용합니다.
(메인메모리로의 접근하는 경우보다, Cahce를 사용할때 훨씬 빨라집니다.)
다중 프로세스의 경우, 이 캐쉬메모리에 올리는 데이터를 계속 갱신시켜야 합니다.
하지만, 다중 스레드의 경우 A스레드, B스레드 모두 메모리를 공유하기 때문에
데이터를 갱신시킬 필요가 없습니다.
이때문에, 스레드는 다중 프로세스보다 수배, 수십배 더 빠릅니다.




일반적으로 스레드는 운영체제 (kernel)에서 관리를 합니다.

Kernel level thread
스레드를 생성하는 대상이 커널 이라면,
커널이 스레드를 제공하고 직접 관리하기 때문에
안전성과, 보다 편하게 다양한 기능을 사용 할 수 있습니다.
하지만, 이경우에 스레드를 관리하는 대상이 커널이기 때문에
커널레벨의 메모리 공간과 유저레벨 메모리 공간 사이에서
잦은 전환이 필요하게 됩니다.

:: 일반 프로세스가 운영체제 메모리에 접근하여
:: 운영체제 동작이 망가지는 현상을 막기 위해
:: 커널 메모리에 쉽게 접근하지 못하도록
:: level에 따른 접근 권한을 두었다.



User level Thread
이경우는, 운영체제가 스레드의 존재를 모르고 오로지
프로세스에 대해서만 context switching을 하는 경우로,
스레드에 대한 시스템콜을 지원하지 않는 운영체제에서의 스레드를 말합니다.
따라서 이경우엔, 커널레벨 스레드의 단점인 커널레벨에 접근하는 것이
필요하지 않기 때문에 속도가 빠릅니다.
또한, Thread Library를 이용하여 프로그래밍 하기 때문에
다양한 운영체제에 대한 호환성이 뛰어납니다.
하지만 process context switching 과정에서, 커널이
스레드의 존재를 모르기 때문에 발생하는 문제점이 존재합니다.