728x90
Thread가 떠오른 배경
- 프로세스는 너무 무겁다
- 각각의 프로세스는 address space를 가져서 code와 data를 따로 차지한다
- OS 자원과 정보
- Hardware State
- 프로세스를 구성하기 위한 공간과 data structure가 필요하기 때문에 새로운 프로세스를 생성하는 비용이 너무 비싸다
- OS를 거쳐서 IPC를 하는 비용이 너무 비싸다
위와 같은 치명적인 이유들로 Thread가 부상되었고 다음의 특징을 가진다
- code와 data 영역을 공유한다
- 같은 권한을 가진다
- 자원들을 공유한다
- 자신만의 hardware state를 가진다
프로세스가 모든 자원과 공간을 독립적으로 가지고 있는 개체라고 한다면 스레드는 공통된 부분은 공유하고 필요한 부분만 독립적으로 구성되어있다.
Process vs. Thread
- 스레드는 하나의 프로세스 안에 존재한다
- 프로세스는 여러 개의 스레드를 가질 수 있다
- 스레드는 같은 address space를 가지기 때문에 sharing data가 싸다
- 최근에 프로세스는 스레드를 담기 위한 컨테이너의 역할을 주로 수행한다
- 프로세스에 비해 스레드가 더 dynamic 하다
이런 점들은 throughput, responsiveness, resource sharing, economy, utilization 같은 부분들에서 훨씬 뛰어나기 때문에 이제는 thread를 통해 multiprogramming을 하는 경우가 대부분이다.
Pthread
이제 threads interface 중 가장 대표적인 POSIX Thread에 대해 살펴보려고 한다.
- Thread creation / termination
- #include <pthread.h>
- gcc library libpthread.a : -lpthread
- int pthread_create (pthread_t *tid, pthread_attr_t *attr, void *(start_routine)(void *), void *arg)
- tid: thread의 id로 OS가 부여한다
- *attr: pthread의 속성을 설정하는 것으로 default는 NULL이다
- (void *): 수행할 함수
- *arg: 함수에 전달할 인자
- void pthread_exit (void *retval)
- pthread를 종료한다
- int pthread_join (pthread_t tid, void **thread_return)
- parent thread가 child thread가 종료되기를 기다리는 함수로 프로세스의 waitpid 함수와 같은 기능
Threading Issues
- fork() & exec()
- 만약 하나의 프로세스에 여러 개의 thread들이 동작하고 있다고 가정해보자. fork() 시 프로세스 안에 있는 모든 thread들이 복제되는 것일까?
- Pthread에서는 fork()를 호출하는 thread만 복제된다
- Unix standard에서 fork()은 프로세스 안에 있는 모든 thread를 복제한다
- Unix standard에서 fork1()은 fork()를 호출하는 thread만 복제된다
- 일반적으로 exec()은 프로세스 전체를 대체한다
- Thread cancellation
- Asynchronous cancellation
- target thread를 즉시 종료한다
- 만약 target thread가 자원을 가지고 있을 시 문제가 발생할 수도 있다
- Deferred cancellation (default)
- target thread가 바로 종료되지 않는다
- pthread_testcancel()을 통해 thread 스스로 cancel 되어야 하는지를 주기적으로 check 하여 종료되어야 한다고 확인 시 종료된다
- Cancellation APIs
- int pthread_cancel (pthread_t thread): return 0, error시 return -1
- int pthread_setcancelstate (int state, int *oldstate): cancel 허용 여부를 결정한다. oldstate는 이전의 state로 복구를 위해 필요하다
- int pthread_canceltype (int type, int *oldtype): deferred, asynchronous 같이 cancel의 타입을 결정한다
- Asynchronous cancellation
- Signal handling
- signal이 왔을 때 어디에서 받을 것인가에 대한 문제이다. 프로세스 안의 모든 thread, 특정 thread, signal을 요청한 thread 등 여러 가지 방법이 있지만 일반적으로 signal에 unblock인 thread 중 하나가 받는다.
- Thread-Local Storage
- 프로세스 안의 thread들이 프로세스의 데이터를 공유하는 영역
- TLS는 thread마다 자신만의 데이터 copy를 가질 수 있도록 한다
- 지역변수와의 차이점은 지역변수는 하나의 함수 안에서만 보이지만 TLS는 해당 thread 안에서는 다 보인다는 점에서 static 변수와 유사하다
- Using libraries
- errno: 오류 코드의 매크로 번호
- Easy sharing but error-prone
- 전역 변수는 thread들 간에 쉽게 공유되지만 명시적이 아닌 묵시적으로 동기화를 할 시 error가 발생할 수 있다. 또한, 포인터처럼 주소를 넘겨주는 작업은 caller와 callee 사이를 넘어오면서 주소 값이 변할 수 있기 때문에 바람직하지 않다
Kernel-level Threads
- OS가 관리하는 thread
- OS가 thread와 프로세스를 모두 관리한다
- 모든 thread의 실행은 kernel의 제어를 받는다
- OS가 시스템의 모든 thread들의 스케줄링을 담당한다
- 만약, 어느 프로세스 안의 하나의 thread가 block 상태로 빠진다면 OS가 이를 알아채고 그 프로세스 안의 다른 thread를 실행시킬 수 있다
- I/O와 CPU의 overlap이 가능하다
- kernel을 거치지만 그럼에도 프로세스보다는 싸다
- Windows, Mac OS, Linux 등 대부분의 OS가 이 방식을 채택
- 한계
- 여전히 비싼 편에 속한다
- 높은 수준의 병행성을 요구할 시, 더 적은 비용의 thread가 요구된다
- thread operation을 함수 호출만큼 빠르게 할 수 없다
- Thread operation이 모두 system call이다
- thread operation을 할 때마다 protection boundary를 넘어가야 되고 이것은 같은 프로세스 내의 thread라도 마찬가지여서 비효율적이다
- thread마다 kernel state를 유지시켜야 하므로 동시에 위치시킬 수 있는 thread의 수가 제한적이다 (~ 1000)
- kernel-level thread는 프로그래머, 언어, 시스템에 모두 지원을 받을 수 있어야 한다
- 여전히 비싼 편에 속한다
User-level Threads
- 동기
- thread를 더 값싸고 빠르게 커널의 도움 없이 user level 선에서 실행시키기 위해
- library 수준에서 처리되므로 이식성을 높이고자
- 장점
- 각각의 thread는 PC, registers, stack, TCB (Thread Control Block)에 의해 간단히 표시된다
- thread를 생성, switching, 동기화시키는 것이 함수 호출 수준으로 동작한다
- kernel-level thread에 비해 10~100배 빠르다
- 한계
- OS에 보이지 않는다
- OS와 합이 잘 맞지 않는다
- OS가 잘못된 결정을 할 가능성이 높아진다
- idle 상태에 있는 thread들을 스케줄링할 수 있다
- 프로세스 안에 ready 상태의 다른 thread가 존재함에도 하나의 thread가 block 상태라는 이유로 프로세스 전체가 block 된다
- lock을 소유하고 있는 thread를 unscheduling 시키지 않을 수 있다
- 위의 경우들은 모두 OS가 user-level thread를 볼 수 없기 때문에 발생한다
- 이를 해결하기 위해서는 kernel과 user-level thread manager (library) 간의 협력이 요구된다
- OS에 보이지 않는다
'컴퓨터 공학 전공 > 운영체제' 카테고리의 다른 글
Process Synchronization (1) (0) | 2020.04.02 |
---|---|
CPU Scheduling (0) | 2020.04.02 |
Process (0) | 2020.04.01 |