스레드의 장점
- 비동기 이벤트를 효율적으로 처리할 수 있다.
- 공유 메모리 다중프로세서에서 병렬 성능을 얻을 수 있다.
- 각 스레드는 스택과 CPU 상태(즉, 레지스터)로 구성된 실행 단위
- Multiple 스레드는 Multiple 프로세스와 유사하지만, 작업 내의 여러 스레드는 동일한 코드, 전역 변수 및 힙을 사용.
- Unix에서 두 개의 프로세스는 운영 체제를 통해서만 통신 가능 (예: 파일, 파이프, 소켓)
- 그러나 작업 내의 두 스레드는 메모리를 통해 통신 가능
스레드를 사용하여 프로그램을 작성할 때, 이들이 동시에 실행된다고 가정한다.
- 각 스레드가 자체 CPU에서 실행되는 것처럼 보여야 하며, 모든 스레드가 동일한 메모리를 공유하는 것처럼 보여야 한다.
멀티태스킹
단일 프로세서에서 멀티스레딩은 일반적으로 시분할 다중화(time-division multiplexing)로 발생(멀티태스킹처럼)
- 프로세서는 다른 스레드 간을 전환
- 이 문맥 전환이 일반적으로 충분히 빈번하게 발생하여 사용자가 스레드 또는 작업이 동시에 실행되는 것으로 인식하게 만든다.
- 다중 프로세서 또는 멀티코어 시스템에서는 스레드 또는 작업이 실제로 동시에 실행된다. 각 프로세서 또는 코어가 특정한 스레드나 작업을 실행한다.
- 많은 최신 운영 체제는
- 프로세스 스케줄러를 통해 시분할 및 멀티프로세서 스레딩을 직접 지원한다.
- 운영 체제 커널은 프로그래머가 시스템 호출 인터페이스를 통해 스레드를 조작할 수 있도록 한다.
프로세스 VS 스레드
스레드는 전통적인 멀티태스킹 운영 체제 프로세스와 구별된다.
프로세스는
- 일반적으로 독립적이며,
- 상당한 상태 정보를 가지며,
- 별도의 주소 공간을 가지며,
- 시스템에서 제공하는 프로세스 간 통신 메커니즘을 통해서만 상호 작용한다.
- 프로세스는 커널 스케줄링의 가장 "무거운" 단위
- 프로세스는 운영 체제에 의해 할당된 리소스를 소유
- 리소스에는 메모리, 파일 핸들, 소켓, 장치 핸들, 창 등이 포함됩니다.
- 프로세스는 주소 공간이나 파일 리소스를 공유하지 않는다.
- 명시적인 방법으로 파일 핸들을 상속하거나 공유 메모리 세그먼트를 사용하거나 동일한 파일을 공유 방식으로 매핑하는 경우를 제외
- 프로세스는 일반적으로 선점형 멀티태스킹이 적용된다.
다중 스레드는
- 일반적으로 프로세스의 상태 정보를 공유하며, 메모리 및 기타 리소스를 직접 공유한다.
- 동일한 프로세스 내의 스레드 간의 문맥 전환은 일반적으로 프로세스 간의 문맥 전환보다 빠르다.
- 스레드는 커널 스케줄링의 가장 "가벼운" 단위
- 각 프로세스 내에는 최소한 하나의 스레드가 존재
- 여러 스레드가 하나의 프로세스 내에 존재할 수 있다면, 그들은 동일한 메모리와 파일 리소스를 공유합
- 스레드는 운영 체제의 프로세스 스케줄러가 선점형이라면 선점형으로 멀티태스킹됩니다.
- 스레드는 스택, 프로그램 카운터를 포함한 레지스터의 복사본 및 스레드 지역 저장소(있는 경우)를 제외하고는 리소스를 소유하지 않는다.
- "커널 스레드"와 "사용자 스레드" 사이에는 구별이 있는데
- 커널 스레드는 커널에 의해 관리되고 스케줄링되며
- 사용자 스레드는 사용자 영역에서 관리되고 스케줄링됩니다.
User Space
전통적인 운영 체제는 일반적으로 가상 메모리를 커널 공간과 사용자 공간으로 구분
커널 공간
- 커널 실행, 커널 확장 및 일부 장치 드라이버에 엄격히 예약되어 있다.
- 대부분의 운영 체제에서 커널 메모리는 디스크로 스왑되지 않는다.
사용자 공간
- 모든 사용자 모드 응용 프로그램이 작업하는 메모리 영역이며, 필요할 때 이 메모리는 스왑될 수 있다.
Pthreads
위 표는 시간 결과를 비교한다.
- fork() 서브루틴과 pthreads_create() 서브루틴에 대한 것
- 타이밍은 50,000개의 프로세스/스레드 생성을 반영하며
- 단위는 초이며, 최적화 플래그가 없다.
POSIX 스레드 함수
pthread_cancel
- 다른 스레드를 종료함
pthread_create
- 스레드를 생성함
pthread_detach
- 스레드가 자원을 해제하도록 설정함
pthread_equal
- 두 스레드 ID의 동일성을 테스트
pthread_exit
- 프로세스를 종료하지 않고 스레드를 종료함
pthread_kill
- 스레드에 신호를 보냄
pthread_join
- 스레드를 기다림
pthread_self
- 자신의 스레드 ID를 확인함
대부분의 함수는 성공하면 0을 반환하고 실패하면 0이 아닌 오류를 반환
- errno를 설정하지 않음
POSIX 스레드 함수 중 어느 것도 EINTR을 반환하지 않으며, 중단된 경우 재시작할 필요가 없다.
Referencing threads by ID
#include <pthread.h>
pthread_t pthread_self(void);
pthread_t pthread_equal(thread_t t1, thread_t t2);
pthread_self
- 자신의 ID를 확인함
pthread_equal
- pthread_t는 구조체일 수 있음
- 두 값이 동일하면 0이 아닌 값을 반환하고, 그렇지 않으면 0을 반환함
Detaching
#include <pthread.h>
int pthread_detach(pthread_t thread);
- 만약 스레드가 분리된 스레드가 아니라면, 스레드는 종료될 때 자원을 해제하지 않는다.
- 이 함수는 스레드의 내부 옵션을 설정하여 스레드의 저장소가 종료될 때 회수될 수 있도록 지정한다.
- 분리된 스레드는 종료될 때 상태를 보고하지 않는다.
- 성공하면 0을 반환하고, 실패하면 0이 아닌 값을 반환한다.
Joining
#include <pthread.h>
int pthread_join(pthread_t thread, void **value_ptr);
호출 스레드의 대상 스레드가 종료될 때까지 호출 스레드를 중단
- 분리되지 않은 스레드의 자원은 다른 스레드가 pthread_join을 호출하거나 전체 프로세스가 종료될 때까지 해제되지 않음
- thread: 대상 스레드
- value_ptr: 반환 상태에 대한 포인터의 위치. NULL이면 호출자는 상태를 검색하지 않음
- 성공하면 0, 실패하면 0이 아닌 값을 반환
pthread_join(pthread_self()); →이 문장은 데드락을 생성
Exiting
#include <pthread.h>
void pthread_exit(void* value_ptr);
호출 스레드를 종료시킴
’return'은 암묵적으로 pthread_exit을 호출함
→ value_ptr : 성공 시 ‘pthread_join’에서 사용 가능
Cancellation
#include <pthread.h>
int pthread_cancel(pthread_t thread);
int pthread_setcancelstate(int state, int *oldstate);
- pthread_cancel
- 다른 스레드가 취소되도록 요청함
- 호출자가 취소가 완료될 동안 블록되지 않음
- 성공하면 0을 반환하고, 실패하면 0이 아닌 값을 반환
- 결과는 대상 스레드의 상태와 유형에 따라 다르다
- PTHREAD_CANCEL_ENABLE: 요청 수신
- PTHREAD_CANCEL_DISABLE: 요청 보류됨
- pthread_setcancelstate
- 호출 스레드의 취소 가능 상태를 변경함
- 'state': PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE
- 'oldstate': 이전 상태가 저장됨
- 성공하면 0을 반환하고, 실패하면 0이 아닌 값을 반환함
Cancellation type
#include <pthread.h>
int pthread_setcanceltype(int type, int *oldtype);
void pthread_testcancel(void);
취소의 어려움
- 스레드가 종료되기 전에 해제해야 하는 리소스를 보유하는 경우
- 종료 핸들러에서 항상 리소스를 해제하는 것이 가능하지 않을 수 있음
취소 유형
- 스레드가 취소 요청에 응답하여 종료되는 시점을 제어할 수 있게 함
- PTHREAD_CANCEL_ASYNCHRONOUS
- 언제든지 요청에 대응할 수 있음
- PTHREAD_CANCEL_DEFERRED
- 스레드가 지정된 취소 지점에서만 요청에 응함
pthread_setcanceltype
- 취소 유형을 변경함
pthread_testcancel(void);
- 이 함수를 호출하여 스레드는 코드 내의 특정 위치에 취소 지점을 설정할 수 있음
여러 스레드를 생성할 때는 해당 스레드가 매개변수에 대한 접근을 완료하기 전까지는 스레드의 매개변수를 재사용하지 않는 것이 좋다.
Thread safety
- A thread-safe function
- 여러 스레드가 간섭 없이 함수의 동시적인 실행을 수행할 수 있는 경우
- POSIX는 특정 함수 목록에 나열된 함수를 제외하고 모든 필요한 함수, 표준 C 라이브러리의 함수를 스레드 안전하게 구현해야 한다고 명시하고 있다.
'Study > 시스템프로그래밍' 카테고리의 다른 글
[시스템프로그래밍] 조건 변수와 시그널, Reader-Writer problem에 관하여 (1) | 2023.12.05 |
---|---|
[시스템프로그래밍] Mutex에 관하여 (4) | 2023.12.05 |
[시스템프로그래밍] 시간과 타이머 (0) | 2023.12.03 |
[시스템프로그래밍] Signals (1) | 2023.12.03 |
[시스템프로그래밍] pipe에 관하여 (0) | 2023.11.02 |