[OS] 운영체제(4장) 쓰레드 - 2
4. Thread 라이브러리
thread를 생성하고 관리하기 위한 API 제공
thread 라이브러리 구현
user-level library : 완전히 user space에서 구현
- library 함수 호출은 user space에서의 함수 호출로 이어짐 kernel-level library : library의 코드와 데이터가 kernel space에 존재
- library 함수 호출은 커널에 대한 system call 호출로 이어짐
주요 Thread libraries
- POSIX Pthreads: user- or kernel-level library
- Windows thread: kernel-level library
- Java Thread: Java thread API → 호스트 시스템에서 사용 가능한 thread library로 구현
Pthreads
- Thread 생성 및 동기화를 위한 POSIX 표준 API (IEEE 1003.1c)
- thread library의 동작에 대한 명세(specification)
- 구현방법을 명시한 것은 아님
- UNIX 계열 OS에서 일반적으로 제공됨 (Solaris, Linux, Mac OS X)
- Pthread library 함수
- pthread_create() - thread 생성
- pthread_join() – 다른 thread 종료를 기다림
- pthread_exit() – thread 종료
- pthread_attr_init() – thread attribute를 default 값으로 초기화
- …
5. 묵시적 쓰레딩
- Thread 생성과 관리를 응용 프로그램 개발자가 아닌 compiler와 runtime library에게 맡기는 것
- 멀티코어 병렬 처리를 사용하는 프로그램 설계에 사용
컴파일러에서 멀티 쓰레딩 지원
- Open MP
- GCD (Grand Central Dispatch)
멀티 쓰레딩 관리 방법
- Thread Pool
Thread Pools
Multithreaded server에서의 잠재적 문제점
- thread 생성 오버헤드 : 요청마다 thread를 생성하는 데 시간이 소요됨
- thread 수가 증가에 따른 자원 고갈 가능성 → thread 수에 제한이 필요
해결책 → Thread pool
- 프로세스를 시작할 때에 일정한 수의 thread들을 thread pool에 미리 생성하여 대기함
- 요청을 받을 때마다 pool에 있는 하나의 thread를 깨워서 사용
장점
빠른 속도
- 새 thread 생성 소요시간보다 기존 thread로 서비스하는 것이 더 빠름 pool의 크기로 동시 존재 thread 수 제한 가능
- 병렬 처리 능력 고려 task 생성 방법을 task에서 분리하면 task실행을 다른 방식으로 할 수 있음
- 주기적 실행, 일정시간 후 실행 등
OpenMP(Open Multi-Processing)
- C, C++, Fortran 컴파일러의 directive와 API로 공유 메모리 환경에서의 병렬 프로그래밍 지원
- 병렬 영역에 대하여 코어 개수의 thread를 생성하여 병렬처리
GCD(Grand Central Dispatch)
- Apple Mac OS X, iOS 운영체제에서 지원
- C/C++ 언어의 확장, API, runtime library로 제공
- 병렬 섹션을 구분하여 쓰레딩 관리 지원 – 블록 표시 ^{ }
ˆ{ printf("I am a block"); }
- 블록들은 dispatch queue에 넣고, queue에서 제거될 때에 thread pool에서 가용 thread에 선택하여 할당함
.6 쓰레드 관련 이슈
fork(), exec() 시스템 호출
thread에서 fork()를 호출 할 때의 동작은?
두 가지 fork() 구현 방법 - 응용 프로그램이 선택
- process의 모든 thread들을 복제 : fork - no exec의 경우에 사용
- 생성된 프로세스는 multi-threaded
- 해당 thread만 복제 : fork - exec의 경우에 사용
- 생성된 프로세스는 single threaded
UNIX에서의 Signal handling
Signal
Process에 대한 signal은 CPU에 대한 interrupt와 비슷함
- UNIX에서 프로세스에게 특정 event 발생을 알려주기 위해서 사용
- 동기식 signal (ex) illegal memory access, division by zero
- 비동기식 signal (ex) Ctrl-C로 종료
- signal handler
- signal(signal number로 구분)을 처리하기 위해 사용됨
- signal은 특정 event에 의해 생성되어 process에게 전달됨
- (예) kill 함수 호출 : kill(pid, signal)
- process의 signal handler에서 처리됨
Multithread Process에서의 Signal 처리
Multithreaded process에서의 signal 전달 옵션
- signal이 적용될 thread에게 전달: (예) 동기식 signal
- 모든 thread에게 전달: (예) Ctrl-C와 같은 비동기 signal
- 일부 thread에게 선택적으로 전달
- 비동기 신호를 masking하지 않은 thread에게 전달
- signal을 전달받는 thread 지정:
- 같은 process 내에서 pthread_kill(tid, signal) 함수호출 signal의 유형에 따라서 signal 전달 방법이 정해짐
Thread 취소
target thread(쓰레드 취소 작업이 적용될 쓰레드)가 종료되기 전에 thread를 강제로 중단시키는 것
- (예) pthread_cancel(tid)
두 가지 취소 방식
- 비동기(asynchronous) 취소 : 즉시 target thread를 취소
- 지연(deferred) 취소 : 주기적으로 점검하여 target thread를 취소
thread 취소의 어려운 점
- 자원이 할당되어 있거나 공유 데이터를 갱신하고 있는 thread를 취소할 때에 처리에 어려움이 발생함
- 비동기 취소 방식에서 자원 회수에 문제 발생 가능성
- 지원 취소 방식에서는 취소 시점(cancellation point)에서 안전한 취소가능 여부를 검사하여 취소
- pthread는 기본적으로 지연 취소 방식을 사용
Thread-Local 저장소
Thread-Local Storage(TLS)
thread 자신 만이 접근 가능한 저장 공간
대부분의 thread library가 TLS 지원기능 제공 TLS, local variable, static variable의 비교
- local 변수 – 함수 호출 동안에만 일시적으로 사용
- static 변수 – 프로그램 실행 동안 함수 내의 기억장소를 유지 (같은 함수를 사용하는 thread들은 static 기억장소 공유)
- TLS – static 변수와 비슷하지만, 각 thread별로 분리된 기억장소 사용
Scheduler Activations
경량 프로세스(lightweight process: LWP)
- Many-to-many 모델에서는 user-level thread와 kernel thread 사이에 LWP(lightweight process)라고 하는 중간 자료구조 사용하여 연결
- 각 LWP는 kernel thread에 연결되며 user-thread library에게 virtual processor 같이 보여짐 → 가용 LWP에 user-level thread들을 스케줄링
각 응용에 필요한 LWP 개수
- CPU-bound 응용: 1개의 LWP이면 충분
- I/O intensive 응용: 여러 개의 LWP 필요
Scheduler Activation
- upcall: thread가 block되거나 event가 발생하면 커널에서 signal을 보내어 thread library의 upcall handler를 호출함
- upcall handler는 새 LWP를 할당 받아 실행되고 다른 thread에게 스케줄링 함
댓글남기기